前言
在UI上显示特效是一直是一个比较棘手的问题,一开始的方案是调整UI特效的渲染顺序,设置其sortingLayer和sortingOrder+offset,在每个单独的UI以后渲染。
这种方法能满足大部分的需求,但也有缺点。
如果需要在特效上再盖一层UI的话,由于特效并不属于Canvas的一部分,所以修改Hierarchy并不能改变其渲染顺序,特效会在渲染完Canvas的UI元素以后再进行渲染,所以需要把这个UI的层级通过添加Canvas继续往上抬。
再者无法被RectMask2D和Mask裁剪,除非改造Shader,并手动传入裁剪区域。
最好的方法就是让特效像UI一样,直接按Hierarchy 顺序渲染,并支持遮罩,就是这文章的主角UIParticle。
原理
This package utilizes the new
APIsMeshBake/MashTrailBake(introduced with Unity 2018.2) to render particles through CanvasRenderer.You can render, mask, and sort your ParticleSystems for UI without the necessity of an additional Camera, RenderTexture, or Canvas.
这是项目首页的原理,具体就是通过一个API让例子特效通过CanvasRender进行渲染,这样就和普通的UI没什么不同了。
使用
按官方的教程,直接引入包,添加组件到特效上,直接拖到UI中即可。
改造已有shader以支持遮罩
项目推荐我们使用UIShader,如UIDefault或者UIAdditive。
Mask通过模板测试实现遮罩,RectMask2D通过传入裁剪区域实现。
所以自定义的Shader只需要参考上面的UIShader使其拥有遮罩特效即可,注意RenderQueue设置为Transparent,下面贴一下关键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
}
}
}
总结
至此已经可以像UI一样使用UI特效了,具体的性能分析,参考一下首页。
参考
https://github.com/mob-sakai/ParticleEffectForUGUI
Unity Mask 和RectMask2D原理和区别-CSDN博客
Unity的三级排序层级渲染Layer,sorting layer,order in layer_unity layer 和order-CSDN博客
UGUI:调整Unity中UI和特效的层级关系(特效穿透问题)_unity中特效显示在image背景上 其他ui元素覆盖在特效上 层级怎么处理-CSDN博客