Unity 新手引导教程之 圆形高亮Shader指引效果
1、打开Unity,新建一个工程,然后在途中新建两个按钮,名命名为 TargetButton, Button,并且简单设置按钮鼠标进入绿色显示,具体如下图
2、在工程中新建一个Shader,可以命名为 CircleShader,然后双击或右键 Open C# Project,编辑脚本,具体如下图
3、CircleShader 脚本其实是Unity自带的 UI_Default.shader 修改而来(原shader可以官网下载,下载方法可参见一下百度经验),关键添加的代码如下图
4、CircleShader 具体内容如下:
Shader "Custom/MyCircleShader" {
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
//设置圆心点和园半径
_Center("Center",vector) = (0,0,0,0)
_Slider("Slider",Range(0,1500)) = 1500
}
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_CLIP_RECT
#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;
float2 _Center;
float _Slider;
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = v.texcoord;
OUT.color = v.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif
//大于圆的半径则颜色显示正常,园园内透明
color.a *= (distance(IN.worldPosition.xy, _Center.xy) > _Slider);
color.rgb *= color.a;
return color;
}
ENDCG
}
}
}
5、脚本编译正确,会回到Unity界面,在场景中新建一个 Panel,调整为偏暗色,然后新建一个 Material 可以命名为 CircleShader,把 Shader 设置为 CircleShader,把材质赋给 Panel ,具体如下图
6、在工程中,新建一个脚本,命名为 CircleShaderController,双击脚本或者右键 Open C# Project 打开脚本编辑,具体如下图
7、CircleShaderController 脚本具体的代码和代码说明如下图
8、CircleShaderController 脚本具体内容如下:
using UnityEngine;
using UnityEngine.UI;
public class CircleShaderController : MonoBehaviour {
/// <summary>
/// 要高亮显示的目标
/// </summary>
public Image Target;
/// <summary>
/// 区域范围缓存
/// </summary>
private Vector3[] _corners = new Vector3[4];
/// <summary>
/// 镂空区域圆心
/// </summary>
private Vector4 _center;
/// <summary>
/// 镂空区域半径
/// </summary>
private float _radius;
/// <summary>
/// 遮罩材质
/// </summary>
private Material _material;
/// <summary>
/// 当前高亮区域的半径
/// </summary>
private float _currentRadius;
/// <summary>
/// 高亮区域缩放的动画时间
/// </summary>
private float _shrinkTime = 0.5f;
/// <summary>
/// 世界坐标向画布坐标转换
/// </summary>
/// <param name="canvas">画布</param>
/// <param name="world">世界坐标</param>
/// <returns>返回画布上的二维坐标</returns>
private Vector2 WorldToCanvasPos(Canvas canvas, Vector3 world)
{
Vector2 position;
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform,
world, canvas.GetComponent<Camera>(), out position);
return position;
}
private void Awake()
{
//获取画布
Canvas canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
//获取高亮区域的四个顶点的世界坐标
Target.rectTransform.GetWorldCorners(_corners);
//计算最终高亮显示区域的半径
_radius = Vector2.Distance(WorldToCanvasPos(canvas, _corners[0]),
WorldToCanvasPos(canvas, _corners[2])) / 2f;
//计算高亮显示区域的圆心
float x = _corners[0].x + ((_corners[3].x - _corners[0].x) / 2f);
float y = _corners[0].y + ((_corners[1].y - _corners[0].y) / 2f);
Vector3 centerWorld = new Vector3(x, y, 0);
Vector2 center = WorldToCanvasPos(canvas, centerWorld);
//设置遮罩材料中的圆心变量
Vector4 centerMat = new Vector4(center.x, center.y, 0, 0);
_material = GetComponent<Image>().material;
_material.SetVector("_Center", centerMat);
//计算当前高亮显示区域的半径
RectTransform canRectTransform = canvas.transform as RectTransform;
if (canRectTransform != null)
{
//获取画布区域的四个顶点
canRectTransform.GetWorldCorners(_corners);
//将画布顶点距离高亮区域中心最远的距离作为当前高亮区域半径的初始值
foreach (Vector3 corner in _corners)
{
_currentRadius = Mathf.Max(Vector3.Distance(WorldToCanvasPos(canvas, corner), center),
_currentRadius);
}
}
_material.SetFloat("_Slider", _currentRadius);
}
/// <summary>
/// 收缩速度
/// </summary>
private float _shrinkVelocity = 0f;
private void Update()
{
//从当前半径到目标半径差值显示收缩动画
float value = Mathf.SmoothDamp(_currentRadius, _radius, ref _shrinkVelocity, _shrinkTime);
if (!Mathf.Approximately(value, _currentRadius))
{
_currentRadius = value;
_material.SetFloat("_Slider", _currentRadius);
}
}
}
9、脚本编译正确,回到 Unity界面,把脚本赋给 Panel,并把 TargetButton 赋给脚本,具体如下图
10、运行场景,圆形高亮指引效果初实现,但是目标按钮由于Panel遮罩不能点击,具体如下图
11、在工程中新建一个脚本 EventPenetrate,使得点击事件可以渗透过 Panel,店家到目标按钮,双击脚本或右键 Open C# Project,具体如下图
12、EventPenetrate 脚本的具体代码和代码说明如下图
13、EventPenetrate 脚本具体内容如下:
using UnityEngine;
using UnityEngine.UI;
public class EventPenetrate : MonoBehaviour,ICanvasRaycastFilter {
//作为目标点击事件渗透区域
public Image target;
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
//没有目标则捕捉事件渗透
if (target == null) {
return true;
}
//在目标范围内做事件渗透
return !RectTransformUtility.RectangleContainsScreenPoint(target.rectTransform,
sp, eventCamera);
}
// Use this for initialization
void Start () {
}
}
14、脚本编译正确,回到Unity界面,把脚本挂载到 Panel,把目标按钮赋值给脚本,具体如下图
15、运行场景,现在即实现了圆形高亮指引效果,又可以渗透 Panel 点击到目标按钮,其他按钮不可点击的效果,具体如下图
16、到此,《Unity 新手引导教程之 圆形高亮Shader指引效果》讲解结束,谢谢