强制新手引导一般来说就是限制点击区域,只能点击游戏引导固定的区域.我们的思路就是试用一张遮罩图片来遮罩全屏,然后把想要点击的物体的渲染层级放在最顶层,然后点击遮罩图片的时候使用事件穿透让我们想要点击的物体来接受事件.大概效果如下图
可以看到我们想要点击的按钮图片的渲染层级已经被放在最上层了.只需要自己写shader来改变渲染队列就可以了.和官方内置的shader都一样只是改变了渲染队列
图片shader
Shader "UI/Image Top"
{
Properties
{
_MainTex("Base (RGB), Alpha (A)", 2D) = "white" {}
}
SubShader
{
LOD 200
Tags
{
//在这里改变渲染队列
"Queue" = "Overlay"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Cull Off
Lighting Off
ZWrite Off
Fog{ Mode Off }
ColorMask RGB
AlphaTest Greater .01
Blend SrcAlpha OneMinusSrcAlpha
ColorMaterial AmbientAndDiffuse
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct appdata_t
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.color = v.color;
o.texcoord = v.texcoord;
return o;
}
half4 frag(v2f IN) : COLOR
{
// Sample the texture
half4 col = tex2D(_MainTex, IN.texcoord) * IN.color;
return col;
}
ENDCG
}
}
}
字体shader
Shader "UI/Font Top"
{
Properties
{
_MainTex("Base (RGB), Alpha (A)", 2D) = "white" {}
}
SubShader
{
LOD 200
Tags
{
"Queue" = "Overlay"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Cull Off
Lighting Off
ZWrite Off
Fog{ Mode Off }
ColorMask RGB
AlphaTest Greater .01
Blend SrcAlpha OneMinusSrcAlpha
ColorMaterial AmbientAndDiffuse
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
struct appdata_t
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION;
half4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
half4 frag(v2f IN) : COLOR
{
fixed4 col = IN.color;
col.a *= tex2D(_MainTex, IN.texcoord).a;
return col;
}
ENDCG
}
}
}
还有最后一步,就是需要让事件透过我们的遮罩层,让我们的按钮来响应点击,下面上代码
public class GuidePostEvent : MonoBehaviour , IPointerClickHandler
{
//监听点击
public void OnPointerClick(PointerEventData eventData)
{
//事件穿透
PassEvent(eventData, ExecuteEvents.pointerClickHandler);
}
public void PassEvent<T>(PointerEventData data, ExecuteEvents.EventFunction<T> function)
where T : IEventSystemHandler
{
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(data, results);
GameObject current = data.pointerCurrentRaycast.gameObject;
for (int i = 0; i < results.Count; i++)
{
if (current != results[i].gameObject)
{
//在这里判断事件穿透检测到的对象是不是我们新手引导需要点击的对象
GuideStep step = results[i].gameObject.GetComponent<GuideStep>();
if (step != null)
{
//再判断引导id是否是属于当前的引导id,毕竟我们一个面板上也许会出现很多
//引导对象
int currentStepId = GuideManager.Singleton.GetStepID();
bool exists = Array.Exists<int>(step.StepID, element => element == currentStepId);
if (exists)
ExecuteEvents.Execute(results[i].gameObject, data, function);
}
}
}
}
}
把上面的脚本挂在我们的引导遮罩层就可以了,只需要自己写个脚本挂在点击对象上来接受事件就可以了.