GIF图看起来有点卡顿, 实际上运行是流畅的。
码云:https://gitee.com/NCAA_admin/Alert.git
1.创建一个背景图片Background并设置相应属性值
2.设置Canvas的属性和Game窗口的比例
3.创建一个弹窗的遮罩蒙版 名为Alert的Image,参数设置如下
4.在Alert下创建一个弹出的信息框 名为Message的Image,各参数设置如下
5.在Message下创建一个文本对象 Text,参数设置如下
6.接在也在Alert下创建两个按钮 Confirm和Cancel
7.其中两个按钮的Text参数分别如下
8.创建一个Shader的蒙版,在Assets下创建Shaders文件夹,在Shaders文件夹下创建名为Blur的Shader脚本
10.Shader脚本,内容如下(关于Shader的实现原理和步骤,有时间再做一个专题的解析)
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/Blur"
{
// 属性
Properties
{
// 定义 1-255 范围的半径 默认 1
_Radius("Radius", Range(1, 255)) = 1
}
Category
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Opaque" }
SubShader
{
GrabPass
{
Tags{ "LightMode" = "Always" }
}
Pass
{
Tags{ "LightMode" = "Always" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
return o;
}
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
float _Radius;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))
sum += GRABXYPIXEL(0.0, 0.0);
int measurments = 1;
for (float range = 0.1f; range <= _Radius; range += 0.1f)
{
sum += GRABXYPIXEL(range, range);
sum += GRABXYPIXEL(range, -range);
sum += GRABXYPIXEL(-range, range);
sum += GRABXYPIXEL(-range, -range);
measurments += 4;
}
return sum / measurments;
}
ENDCG
}
GrabPass
{
Tags{ "LightMode" = "Always" }
}
Pass
{
Tags{ "LightMode" = "Always" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
};
struct v2f
{
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
o.uvgrab.zw = o.vertex.zw;
return o;
}
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
float _Radius;
half4 frag(v2f i) : COLOR
{
half4 sum = half4(0,0,0,0);
float radius = 1.41421356237 * _Radius;
#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))
sum += GRABXYPIXEL(0.0, 0.0);
int measurments = 1;
for (float range = 1.41421356237f; range <= radius * 1.41; range += 1.41421356237f)
{
sum += GRABXYPIXEL(range, 0);
sum += GRABXYPIXEL(-range, 0);
sum += GRABXYPIXEL(0, range);
sum += GRABXYPIXEL(0, -range);
measurments += 4;
}
return sum / measurments;
}
ENDCG
}
}
}
}
11.在Assets下创建一个名Materials文件夹,在Materials文件夹下创建名为MaskBlur的Material材质
12.在Alert下指定MaskBlur材质,并设置材质的模糊值为5
13.为了使交互效果具有动画的过度感,在编辑器顶部的菜单栏中 Windows>Asset Store 下打开资源商店
14.搜索DoTween关键词,并进入下载
15.下载完成后点击导入即可
16.在Assets下创建Scripts文件夹,在Scripts下创建Alert.cs脚本
17.Alert.cs脚本内容
using UnityEngine;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//显示Alert会话
public class Alert : MonoBehaviour
{
public static Alert Instance;
private void Awake()
{
Instance = this;
}
[Tooltip("会话对象")] public RectTransform m_alert;
//获取ui blur(alert)初始大小
private Vector2 _uiBlurSize;
//获取ui blur(alert)初始scale
private Vector2 _uiBlurScale;
//透明遮罩层
private RectTransform _transparentMask;
//透明遮罩层的初始颜色值值
private Color _transparentMaskColor;
//获取confirm
private RectTransform _confirm;
//获取confirm初始大小
private Vector2 _confirmSize;
//获取confirm初始scale
private Vector2 _confirmScale;
//获取text对象
private Text _text;
//获取text的大小
private Vector2 _textSize;
//获取text scale
private Vector2 _textScale;
void Start()
{
//判断并且赋值
if (!m_alert)
{
m_alert = transform.GetComponent();
}
//获取uiblur(alert)初始大小
_uiBlurSize = m_alert.rect.size;
_uiBlurScale = m_alert.localScale;
//获取透明遮罩层
_transparentMask = m_alert.GetChild(0).GetComponent();
//透明遮罩层的颜色
_transparentMaskColor = _transparentMask.GetComponent().color;
//获取confirm
_confirm = m_alert.GetChild(1).GetComponent();
//获取confirm初始大小
_confirmSize = _confirm.rect.size;
_confirmScale = _confirm.localScale;
//获取text对象
_text = _confirm.GetChild(0).GetComponent();
//获取text的大小
_textSize = _text.GetComponent().rect.size;
_textScale = _text.rectTransform.localScale;
//确定取消按钮
_Confirm();
_Cancel();
//初始设置隐藏
if (m_hideOnStart)
_SetHideImmediate();
}
///
/// 无动画立即隐藏
///
public void _SetHideImmediate()
{
//设置隐藏
m_alert.gameObject.SetActive(false);
_confirm.gameObject.SetActive(false);
_text.gameObject.SetActive(false);
_transparentMask.gameObject.SetActive(false);
//宽高设置0
m_alert.DOScale(Vector3.zero, 0);
_confirm.DOScale(Vector3.zero, 0);
//设置遮罩层alpha = 0
_transparentMask.GetComponent().DOFade(0, 0);
}
///
/// 开始时为隐藏状态
///
[Tooltip("开始时为隐藏状态")]
public bool m_hideOnStart = true;
///
/// 隐藏
///
public void _SetHide()
{
//设置隐藏
_text.gameObject.SetActive(false);
//宽高设置0
m_alert.DOScale(Vector2.zero, _SetShow_duration)
.onComplete = () =>
{
m_alert.gameObject.SetActive(false);
};
_confirm.DOScale(Vector2.zero, _SetShow_duration)
.onComplete = () =>
{
_confirm.gameObject.SetActive(false);
};
//隐藏透明遮罩层
_transparentMask.GetComponent().DOFade(0, _SetShow_duration)
.onComplete = () =>
{
_transparentMask.gameObject.SetActive(false);
};
}
///
/// 显示
///
public void _SetShow()
{
//设置显示
m_alert.gameObject.SetActive(true);
_confirm.gameObject.SetActive(true);
_transparentMask.gameObject.SetActive(true);
//宽高设置成初始大小+5%再回到原来的大小
m_alert.DOScale(_uiBlurScale + _uiBlurScale * 0.05f, _SetShow_duration)
.onComplete = () =>
{
//完成后回到初始大小 时间为原来的1/5
m_alert.DOScale(_uiBlurScale, _SetShow_duration / 5f);
};
_confirm.DOScale(_confirmScale + _confirmScale * 0.05f, _SetShow_duration)
.onComplete = () =>
{
//完成后回到初始大小 时间为原来的1/5
_confirm.DOScale(_confirmScale, _SetShow_duration / 5f);
//并且显示text
_text.gameObject.SetActive(true);
};
//显示透明遮罩层
_transparentMask.GetComponent().DOFade(_transparentMaskColor.a, _SetShow_duration);
}
///
/// 显示动画时间
///
private float _SetShow_duration = 0.3f;
///
/// 按钮的hover效果
///
/// 按钮
public void _OnHover(Transform button)
{
if (!m_inited)
{
m_inited = true;
//获取初始大小
m_initialScale = transform.GetComponent().localScale.x;
}
if (!button.GetComponent()) button.gameObject.AddComponent();
EventTrigger trigger = button.GetComponent();
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.PointerEnter;
entry.callback = new EventTrigger.TriggerEvent();
entry.callback.AddListener(delegate (BaseEventData baseEvent) {
button.GetComponent().DOScale(m_localScale, 0.3f);
});
trigger.triggers.Add(entry);
EventTrigger.Entry entry2 = new EventTrigger.Entry();
entry2.eventID = EventTriggerType.PointerExit;
entry2.callback = new EventTrigger.TriggerEvent();
entry2.callback.AddListener(delegate (BaseEventData baseEvent) {
button.GetComponent().DOScale(m_initialScale, 0.3f);
});
trigger.triggers.Add(entry2);
}
///
/// 变大尺度默认1
///
[Tooltip("变大尺度默认1.2f")]
public float m_localScale = 1.2f;
///
/// 初始的大小
///
private float m_initialScale;
///
/// 是否被初始化
///
private bool m_inited = false;
///
/// 确定
///
public void _Confirm()
{
_OnHover(m_confirm);
m_confirm.GetComponent
18.将Alert.cs脚本拖拽到Alert对象上,并分别将Confirm和Cancel对象拖拽到Alert对应的组件上
19.再在Assets>Scripts文件夹下新建键盘事件的脚本 KeyEvent.cs
20.KeyEvent.cs脚本内容
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeyEvent : MonoBehaviour
{
///
/// 获取Alert组件
///
private Alert alert;
void Start()
{
//实例化组件
alert = Alert.Instance;
}
void Update()
{
//键盘事件
_KeyDown();
}
///
/// 按下键盘执行
///
public void _KeyDown()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
alert._SetShow();
}
}
}
21.在Hierarchy下新建一个脚本管理器的空物体Script,并将KeyEvent.cs脚本附在其上
22.为了让Hierarchy下的组件的层次更加明显,分别新建了三个空物体,具体如下
23.最后运行游戏,按下Esc键弹出信息框