作者:Angels萱萱 | 来源:互联网 | 2023-09-12 17:54
Unity之新手引导shader遮罩事件穿透效果图设计思路1.新手引导我们期待开发内容不影响正常的功能模块,意思就是分层,新手引导在正常功能之上2.
Unity之新手引导shader遮罩事件穿透 效果图
设计思路 1.新手引导我们期待开发内容不影响正常的功能模块,意思就是分层,新手引导在正常功能之上 2.新手引导层级用一层深色bg显示遮住正常功能层级,在需要引导的位置留出高亮区域 3.在这个新手引导层做事件渗透,给指定的对象或UI做事件渗透,如果点击交互位置处于指定UI或对象范围内,让事件渗透新手引导层,到正常功能层。
场景搭建 搭建两个层级
一个正常功能层级为Canvas下,一个新手引导层级在GuideHolder下。
制作新手引导的预制体 材质使用我们特制的带镂空效果的材质shader,并挂载一个事件渗透作用的脚本
代码 这里有两个比较重要的内容,一个是遮罩层是深色的,并要镂空指定区域做高亮,这里使用shader去制作效果图。二是在合适时机做指定区域的事件渗透。
GuideMask.cs
public void CreateCircleMask ( Vector3 pos, float rad, GameObject target) { ShowGuideMask ( ( ) => { ShowTween = true ; ev. SetTargetImage ( target) ; _rectTrans. sizeDelta = Vector2. zero; _materia. SetFloat ( "_MaskType" , 0f ) ; CurRadNum = rad; _materia. SetVector ( "_Origin" , new Vector4 ( pos. x, pos. y, rad + 1000 , 20 ) ) ; } ) ; } public void ShowGuideMask ( Action callback) { ShowTween = false ; if ( _rectTrans == null ) { ResMgr. Instance. Load ( "GuideSystem" , ( obj) => { guide = Instantiate ( ( GameObject) obj, ISceneManager. Instance. GuideHolder) ; _rectTrans = guide. GetComponent < RectTransform> ( ) ; _rawImage = guide. GetComponent < RawImage> ( ) ; _rawImage. color = new Color ( 1 , 1 , 1 , 1 ) ; _materia = _rawImage. material; ev = guide. GetComponent < EventPenetrate> ( ) ; callback ( ) ; } ) ; } else { callback ( ) ; } }
GuideMask.shader
Shader "UI/GuideMask" { Properties{ [ PerRendererData ] _MainTex ( "Sprite Texture" , 2D ) = "white" { } _Color ( "Tint" , Color) = ( 1, 1, 1, 1) _Blur ( "边缘虚化的范围" , Range ( 1 , 1000 ) ) = 100 _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 _Origin ( "Circle" , Vector) = ( 0 , 0 , 0 , 0 ) _MaskType ( "Type" , Float) = 0 } SubShader{ Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" } Stencil{ Ref[ _Stencil] Comp[ _StencilComp] Pass[ _StencilOp] ReadMask[ _StencilReadMask] WriteMask[ _StencilWriteMask] } Cull OffLighting OffZWrite OffZTest[ unity_GUIZTestMode] Blend SrcAlpha OneMinusSrcAlphaColorMask[ _ColorMask] Pass{ Name "Default" CGPROGRAM#pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc" #include "UnityUI.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID} ; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPosition : TEXCOORD1; UNITY_VERTEX_OUTPUT_STEREO} ; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; float4 _Origin; float _MaskType; float _Blur; v2f vert ( appdata_t IN) { v2f OUT; UNITY_SETUP_INSTANCE_ID ( IN) ; UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO ( OUT) ; OUT. worldPosition = IN. vertex; OUT. vertex = UnityObjectToClipPos ( OUT. worldPosition) ; OUT. texcoord = IN. texcoord; OUT. color = IN. color * _Color; return OUT; } sampler2D _MainTex; fixed4 frag ( v2f IN) : SV_Target{ half4 color = ( tex2D ( _MainTex, IN. texcoord) + _TextureSampleAdd) * IN. color; if ( _MaskType == 0 ) { float dis = distance ( IN. worldPosition. xy, _Origin. xy) ; clip ( dis - ( _Origin. z - _Blur) ) ; fixed tmp = step ( dis, _Origin. z) ; color. a *= ( 1 - tmp) + tmp * ( dis - ( _Origin. z - _Blur) ) / _Blur; } else if ( _MaskType == 1 ) { if ( UnityGet2DClipping ( IN. worldPosition. xy, _Origin) ) { color. a = 0 ; } } else if ( _MaskType == 2 ) { if ( UnityGet2DClipping ( IN. worldPosition. xy, _Origin) ) { color. a = 0 ; #ifdef UNITY_UI_CLIP_RECT color. a *= UnityGet2DClipping ( IN. worldPosition. xy, _Origin) ; #endif } } return color; } ENDCG} } }
调用
GuideMask. Instance. CreateCircleMaskoffset ( button2. gameObject, 0 , null ) ; GuideMask. Instance. CloseGuideMask ( ) ;
工程项目 链接:https://pan.baidu.com/s/1v4laE9QdqRGWKqfKJpnkxQ 提取码:s8qc