[Shader]新手引导中的遮罩裁剪

Posted tianjiuwan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Shader]新手引导中的遮罩裁剪相关的知识,希望对你有一定的参考价值。

最近要写新手引导,记录一下

蒙黑(层级最上,蒙住整个UI,有镂空裁剪)镂空区域btn(是一个button 动态改变位置) 引导UI(做新手引导的UI) 活动UI(主动弹出的活动UI 层级位于引导UI上)

当然还有引导的小姐姐头像对话框以及镂空区域有特效提示

之前做法:蒙黑背景计算镂空区域,蒙黑镂空区域有一个btn,btn的点击可以渗透下去

                   但是会出现一种问题,点击镂空区域btn,可能发生异常,下面的按钮没有被渗透点击,但是这一步骤怎么办?我们也不方便记录

                   还有一个问题,如果在引导的时候出现一个活动UI(一种全屏UI,在活动时间主动弹出),这个时候引导UI的层级可能小于活动UI层级,当然可以在引导时候禁止UI其他UI打开,这个方法的

                  点击事件还是可以渗透活动UI到引导UI

之后做法:蒙黑依旧,蒙黑背景计算镂空区域,蒙黑镂空区域有一个btn

                   这个btn的点击事件不用渗透下去,不再挂载渗透点击脚本,而是监听点击事件

                   这个btn的点击事件的逻辑:调用引导步骤中按钮的点击事件 如果是button evt = button.onClick evt.Invoke() 如果是toggle tog.isOn = true 

                   这个方法我配置的是指引按钮的路径,可能我们在Find的时候UI还没有打开,Find不到的时候我们递归调用(当然做一个CD时间)

                   还有一个问题是获取指引按钮的位置问题,UI刚打开的时候我们Find到了按钮,但是这个时候可能按钮还在做动画,那我们也需要持续更新位置信息(当然可以做一个CD tween做缓动)

                   还有一个问题是按钮的世界坐标获取,按钮的父节点有很多,父节点的锚点各种各样,我们需要把按钮的位置转到maskBg(蒙黑UI)之下

                   local pos = self.maskBg.gameObject.transform:InverseTransformPoint(go.transform.position)

做法可能多种多样,需求也是多种多样,有时候需要考虑需求的时候,需要改变策略,随机应变了

1<效果图>

   

 

<2>抠了个圆形

  

<3>属性说明(这里定义了2个变量  圆心 Type)

圆心:Vector(X Y Z W)      矩形: 如果是矩形按钮 X Y为坐标 Z W为宽高      圆形:X Y为坐标,Z为直径

Type:0为圆形裁剪   1为矩形裁剪

上面四张图已经展示得很清楚了 shader里面的计算也很简单 对比了一下uv与中心点的位置关系

<4>配置表(配置的Lua)

               --之前配置格式 这种格式配置了每个步骤的位置信息 每一步开始直接做动画位移 方便;但是策划得配置这些区域 还是比较麻烦

GuideConfig ={}

--openCondition type 1=任务完成开启 v任务code 2=等级达到开启 v等级 3=系统开启时开启 v系统code

--pos x y z w x,y 坐标 z,w 宽高(圆只有Z直径)
--maskType 0 圆形裁剪 1 方形裁剪

GuideConfig[10086] = {}
GuideConfig[10086].openCondition = {type =1 , value1 = 11022}
GuideConfig[10086].step={}
GuideConfig[10086].step[1] ={maskType = 0, pos = \'597;-35;86;86\' , say = \'在这里打开技能面板\'}
GuideConfig[10086].step[2] ={ pos = \'-569.2;64.8;141.5;72.5\' , say = \'点击切换到天赋页签\'}
GuideConfig[10086].step[3] ={ pos = \'-209.6;91.9;88;88\' ,say = \'点击这里选中一个天赋\'}
GuideConfig[10086].step[4] ={ pos = \'436.9;-206.8;145;60\' ,say = \'接下来升级这个天赋吧\'}

 

---现在的配置格式 

GuideConfig ={}

--openCondition type 1=任务完成开启 v任务code 2=等级达到开启 v等级 3=系统开启时开启 v系统code

--pos x y z w x,y 坐标 z,w 宽高(圆只有Z直径)
--maskType 0 圆形裁剪 1 方形裁剪

GuideConfig[10086] = {}
GuideConfig[10086].openCondition = {type =1 , value1 = 11022}
GuideConfig[10086].step={}
GuideConfig[10086].step[1] ={maskType = 0,path=\'UIRoot/MainUILayer/MainBottomRight/LastRightParent/LastRightPanel/SkillBtn\' , say = \'在这里打开技能面板\'}
GuideConfig[10086].step[2] ={path=\'UIRoot/ViewLayer/SkillMain/Selection/b_skillGift\', say = \'点击切换到天赋页签\'}
GuideConfig[10086].step[3] ={path=\'UIRoot/ViewLayer/SkillMain/GiftSkillPanel(Clone)/midVel/gifts/b_attackView/content/giftItem4\',say = \'点击这里选中一个天赋\'}
GuideConfig[10086].step[4] ={path=\'UIRoot/ViewLayer/SkillMain/GiftSkillPanel(Clone)/rightVel/bg/b_levelUpBtn\',say = \'接下来升级这个天赋吧\'}

<5>源码

Shader "Tang/GuideMask"
{
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
//中心
_Origin("圆心",Vector) = (0,0,0,0)
//裁剪方式 0圆形 1圆形
_MaskType("Type",Float) = 0
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", 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 Off
Lighting Off
ZWrite Off
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]

Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0

#include "UnityCG.cginc"
#include "UnityUI.cginc"

#pragma multi_compile __ UNITY_UI_ALPHACLIP

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;

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
{
float2 uv = IN.texcoord;
half4 col = IN.color;
//开始裁剪
//外部直接给坐标 宽 高 GPU计算比率
float posX = (_Origin.x + 640) / 1280;
float posY = (_Origin.y + 360) / 720;
float2 pos = float2(posX, posY);
if (_MaskType == 0) {
posX = posX * 1280 / 720;
pos = float2(posX, posY);
float rid = _Origin.z / 720 / 2;
uv.x = uv.x * 1280 / 720;
float2 nor = uv-pos;
if (length(nor) < rid)
col.a = 0;
}
else {
float w = _Origin.z / 1280 / 2;
float h = _Origin.w / 720 / 2;
if (uv.x > pos.x - w && uv.x<pos.x + w && uv.y>pos.y - h && uv.y < pos.y + h)
col.a = 0;
}

half4 color = (tex2D(_MainTex,uv) + _TextureSampleAdd) * col;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
clip(col.a);
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif

return color;
}
ENDCG
}
}
}

 

以上是关于[Shader]新手引导中的遮罩裁剪的主要内容,如果未能解决你的问题,请参考以下文章

Unity之引导功能遮罩事件穿透

Unity之引导功能遮罩事件穿透

2D游戏新手引导点光源和类迷雾实现

最新版微信/QQ的遮罩引导代码实现 点击链接或扫码提示浏览器打开

cocos2dx 新手引导

如何简单的实现新手引导之UGUI篇