Home

Awesome

<img alt="UIParticleIcon" src="https://github.com/mob-sakai/ParticleEffectForUGUI/assets/12690315/d76e105e-a840-4f61-a1f6-8cf311c0812d" width="26"/> Particle Effect For UGUI (UI Particle) <!-- omit in toc -->



PRs Welcome

<< 📝 Description | 📌 Key Features | 🎮 Demo | ⚙ Installation | 🚀 Usage | 🛠 Development Note | 🤝 Contributing >>

📝 Description <!-- omit in toc -->

This package uses the new APIs MeshBake/MeshTrailBake (introduced in Unity 2018.2) to render particles through CanvasRenderer.
You can render, mask, and sort your ParticleSystems for UI without the need for an additional Camera, RenderTexture, or Canvas.

<br><br>

📌 Key Features

<br><br>

🎮 Demo

<br><br>

⚙ Installation

This package requires Unity 2018.3 or later.

Install via OpenUPM

Install via UPM (with Package Manager UI)

Install via UPM (Manually)

Install as Embedded Package

  1. Download a source code zip file from Releases and extract it.
  2. Place it in your project's Packages directory.

<br><br>

🚀 Usage

Component: UIParticle

UIParticle controls the ParticleSystems that are attached to its own game objects and child game objects.

NOTE: Press the Refresh button to reconstruct the rendering order based on children ParticleSystem's sorting order and z-position.

<br><br>

Basic Usage

  1. Select GameObject/UI/ParticleSystem to create UIParticle with a ParticleSystem. particle
  2. Adjust the ParticleSystem as you like. particle1
<br>

Usage with Your Existing ParticleSystem Prefab

  1. Select GameObject/UI/ParticleSystem (Empty) to create UIParticle. empty
  2. Drag and drop your ParticleSystem prefab onto UIParticle. particle3
<br>

Usage with Mask or RectMask2D Component

If you want to mask particles, set a stencil-supported shader (such as UI/UIAdditive) to the material for ParticleSystem. If you use some custom shaders, see the How to Make a Custom Shader to Support Mask/RectMask2D Component section.

<br><br>

Usage with Script

// Instantiate ParticleSystem prefab with UIParticle on runtime.
var go = GameObject.Instantiate(prefab);
var uiParticle = go.AddComponent<UIParticle>();
uiParticle.scale = 100;

// Control by ParticleSystem.
particleSystem.Play();
particleSystem.Emit(10);

// Control by UIParticle.
uiParticle.Play();
uiParticle.Stop();

<br><br>

Component: UIParticleAttractor

UIParticleAttractor attracts particles generated by the specified ParticleSystem.

<br><br>

Project Settings

<br><br>

🛠 Development Note

Compares the Baking mesh approach with the conventional approach

Performance test results

ApproachFPS on EditorFPS on iPhone6FPS on Xperia XZ
Particle System435722
UIParticleSystem430 (unmeasurable)
Sorting By Canvas434418
UIParticle17124
UIParticle with MeshSharing444530

🔍 FAQ: Why Are My UIParticles Not Displayed Correctly?

If ParticleSystem alone displays particles correctly but UIParticle does not, please check the following points:

<br>

Shader Limitation

The use of UI shaders is recommended.

Built-in shaders are not supported

UIParticle does not support all built-in shaders except for UI/Default.
If their use is detected, an error is displayed in the inspector.
Use UI shaders instead.

(Unity 2018 or 2019) UV.zw components will be discarded

UIParticleRenderer renders the particles based on UIVertex.
Therefore, only the xy components are available for each UV in the shader. (zw components will be discarded).
So unfortunately, UIParticles will not work well with some shaders.

(Unity 2018 or 2019) Custom vertex streams

When using custom vertex streams, you can fill zw components with "unnecessary" data.
Refer to this issue for more information.

<br>

Overheads

UIParticle has some overheads, and the batching depends on uGUI.
When improving performance, keep the following in mind:

How to Make a Custom Shader to Support Mask and RectMask2D Component

<details> <summary>Shader tips</summary>
Shader "Your/Custom/Shader"
{
    Properties
    {
        // ...
        // #### required for Mask ####
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
        _ColorMask ("Color Mask", Float) = 15
        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            // ...
        }

        // #### required for Mask ####
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
        ColorMask [_ColorMask]
        // ...

        Pass
        {
            // ...
            // #### required for RectMask2D ####
            #include "UnityUI.cginc"
            #pragma multi_compile __ UNITY_UI_CLIP_RECT
            float4 _ClipRect;

            // #### required for Mask ####
            #pragma multi_compile __ UNITY_UI_ALPHACLIP

            struct appdata_t
            {
                // ...
            };

            struct v2f
            {
                // ...
                // #### required for RectMask2D ####
                float4 worldPosition    : TEXCOORD1;
            };
            
            v2f vert(appdata_t v)
            {
                v2f OUT;
                // ...
                // #### required for RectMask2D ####
                OUT.worldPosition = v.vertex;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                // ...
                // #### required for RectMask2D ####
                #ifdef UNITY_UI_CLIP_RECT
                    color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif

                // #### required for Mask ####
                #ifdef UNITY_UI_ALPHACLIP
                    clip (color.a - 0.001);
                #endif

                return color;
            }
            ENDCG
        }
    }
}
</details>

<br><br>

🤝 Contributing

Issues

Issues are incredibly valuable to this project:

Pull Requests

Pull requests offer a fantastic way to contribute your ideas to this repository.
Please refer to CONTRIBUTING.md and develop branch for guidelines.

Support

This is an open-source project developed during my spare time.
If you appreciate it, consider supporting me.
Your support allows me to dedicate more time to development. 😊


<br><br>

License

Author

See Also