Unity UGUI粒子层级问题,粒子和Image顺序,粒子裁剪

问题

开发过程中有很多用到粒子特效的时候出现和UI层级冲突,比如粒子需要再同一个界面两个Image中间

解决

一般有三种方案
1.通过rendertexture渲染,可以完美处理层级问题,不过性能不好,多个摄像机
2.直接放到ui界面增加canvas,调整特效sort in layer,不过如果ui特效穿插多,层级不好管理,且多canvas造成合批问题
3.就是这篇文章主要讲的 粒子BakeMesh 优点:可像UGUI一样通过上下调整层级排序,接受Mask处理
下载资源
用法:
文件里面有demo,简单来说就是在特效的父物体上加UIParticle脚本就行

如果是为了解决问题看到这里就可以了,下面是解析怎么实现的

粒子BakeMesh
原理:直接让粒子的网格和贴图在ui基础组件里面渲染
使用接口
ParticleSystemRenderer.BakeMesh和ParticleSystemRenderer.BakeTrailsMesh这里是生成网格信息
CanvasRenderer.SetMesh
CanvasRenderer.SetTexture
把mesh和texture扔给canvasRenderer渲染

代码解析
UIParticle
UIParticle 是粒子的父物体

[RequireComponent(typeof(RectTransform))]
 [RequireComponent(typeof(CanvasRenderer))]
public class UIParticle : MaskableGraphic
{
protected override void OnEnable()
        {
            UIParticleUpdater.Register(this);

CanvasRenderer渲染包含在Canvas中的UI对象,是一个Graphic必须的

UIParticleUpdater
Canvas.willRenderCanvases监听

internal static class UIParticleUpdater
    {
        [RuntimeInitializeOnLoadMethod]
        private static void InitializeOnLoad()
        {
            Canvas.willRenderCanvases -= Refresh;
            Canvas.willRenderCanvases += Refresh;
        }

Q: Canvas.willRenderCanvases监听
A:官方解释:在即将开始 Canvas 渲染前调用的事件。
这让您能够延时处理/更新基于画布的元素,直到即将开始渲染它们之时。在这里做生成粒子的Mesh,再通过调用particle.canvasRenderer.SetMesh,渲染粒子的mesh
Refresh

private static void Refresh(UIParticle particle)
        {
            Profiler.BeginSample("[UIParticle] Bake mesh");
            BakeMesh(particle);
            Profiler.EndSample();

           Profiler.BeginSample("[UIParticle] Set mesh to CanvasRenderer");
            particle.canvasRenderer.SetMesh(particle.bakedMesh);
            Profiler.EndSample();
        }

想了解更多可以下载下来仔细研究

在这里插入图片描述
在你的shader中加入下面
参考

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
        }
    }
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万兴丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值