最近要寫新手引導,記錄一下
蒙黑(層級最上,蒙住整個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
}
}
}