一.问题背景
在项目开发过程中,美术和特效时常会给你出一些难题,比如在一张Image上展示一层特效,然后又在这层特效上展示一张Image,这一坨为一个独立元素,还得在滚动框里滑动,滚动的时候,遮挡逻辑依旧有效。
上图
二.解决方案
方案1.给顶层图片添加Canvas,调整OrderinLayer的值
1.调整Canvas的RenderMode为ScreenSpace-Camera,给RenderCamera一个摄像机。
2.调整粒子特效的Renderer的Order inLayer的数值,因为新建的UI和Canvas的SortingLayer为Defalut,OrderinLayer为0。想要粒子特效在底图之上,其OrderinLayer的值就要比底图的值大,将粒子特效的OrderinLayer的值调为1。
3.将顶图的OrderinLayer值调为2,比粒子特效的数值大即可。但是UGUI的ImageImspector面板是没有OrderinLayer的属性的。给Image添加Canvas,调节其OrderinLayer的值。
方案2.将顶层Image替换为SpriteRenderer,调节OrderinLayer的值
1.调整Canvas的RenderMode为ScreenSpace-Camera,给RenderCamera一个摄像机。
2.调整粒子特效的Renderer的Order inLayer的数值,因为新建的UI和Canvas的SortingLayer为Defalut,OrderinLayer为0。想要粒子特效在底图之上,其OrderinLayer的值就要比底图的值大,将粒子特效的OrderinLayer的值调为1。
3.将Image改为SpriteRenderer,然后调节OrderinLayer的值
方案3.自制UIMaskMaterial,控制粒子特效的显示区间
1.调整Canvas的RenderMode为ScreenSpace-Camera,给RenderCamera一个摄像机。
2.调整粒子特效的Renderer的Order inLayer的数值,因为新建的UI和Canvas的SortingLayer为Defalut,OrderinLayer为0。想要粒子特效在底图之上,其OrderinLayer的值就要比底图的值大,将粒子特效的OrderinLayer的值调为1。
3.在粒子区间放置一个空Image,添加自制的MaskMaterial材质,然后调整特效的Masking为VisibleInsideMask, 在顶层的图片只需要添加 mask遮罩即可遮挡粒子特效了。
上图
三.代码
MaskMaterial使用的Shader的脚本为
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "UI/MaskDefault"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_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
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask 0
Stencil
{
Ref 1
Comp Always
Pass Replace
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
};
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
#endif
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
四.工程项目
链接:https://pan.baidu.com/s/1VByGBqJ7sCjAjkPPkfzW0A
提取码:h56i
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V4的分享
参考:
UGUI粒子遮罩(UI Mask 遮挡粒子)UnityShader实例09:Stencil Buffer&Stencil Test