实现效果:![](https://i-blog.csdnimg.cn/direct/c84732bcf9ac447ea168da48cefe1f70.gif)
实现分析:
在Unity中借助一个 “RenderMode为Overlay” 的Canvas实现。在默认情况下,Canvas自身的RectTransfrom的尺寸会自动适配屏幕尺寸。这样通过 Input.mousePosition 获取的屏幕坐标位置就直接等于Canvas下UI对象的世界position。这样每点击屏幕时,简单设定下“UI特效” 位置(使之与屏幕坐标位置对应)并播放特效即可实现了。
详细流程:
1. 特效贴图的制作![](https://i-blog.csdnimg.cn/direct/97cc2cb6542f42c8b810f3c60971c6d5.png)
需要制作一张这样的在Unity使用的特效贴图,在Unity材质中实时改变此贴图UV来实现的序列帧动画,制作此贴图的大致流程为:网上找一个特效视频或gif图 >> 导出序列帧png图像(最好用PS裁切一下透明区域) >> 使用TexturePackerGUI将序列帧图像整合为一张如此的特效贴图。(虽然直接使用Unity动画一张张的改变图像方式也能实现序列帧动画,但是性能上没有UV变动的方法好)
2.UV变动功能实现
using UnityEngine;
public class UVAnim : MonoBehaviour
{
public int rows = 4;//贴图分割 行数
public int columns = 4;//贴图分割 列数
public float framesPerSecond = 30f;//帧速率
private Material material;
private int index = 0;
private float timer = 0f;
//触发函数,传入世界坐标位置
public void Trigger()
{
if (gameObject.activeSelf == false)
gameObject.SetActive(true);
SetUVInfo(0);
index = 0;
timer = 0f;
}
private void Awake()
{
material = GetComponent<Renderer>().material;
}
private void Update()
{
timer += Time.deltaTime;
if (timer >= 1f / framesPerSecond)
{
timer -= 1f / framesPerSecond;
index++;
if (index >= rows * columns)
{
gameObject.SetActive(false);
}
SetUVInfo(index);
}
}
//设定材质UV的偏移和缩放值
//index:贴图行列均匀分割后,从左上开始的每个小块index
private void SetUVInfo(int index)
{
int row = index / columns;
int col = index % columns;
Vector2 offset = new Vector2((float)col / columns, (float)(rows - 1 - row) / rows);
Vector2 scale = new Vector2(1f / columns, 1f / rows);
material.SetTextureOffset("_MainTex", offset);
material.SetTextureScale("_MainTex", scale);
}
}
也可以在Shader中实现......
3.屏幕点击检测、设定UI特效位置、播放特效 等功能实现
using UnityEngine;
using System.Linq;
public class ClickEffectMgr : MonoBehaviour
{
private bool isInit = false;
private UVAnim uvAnim = null;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Trigger(Input.mousePosition);
}
}
private void TryInit()
{
if (!isInit)
{
//私有变量赋值
uvAnim = GetComponentInChildren<UVAnim>(true);
//自身Canvas
var canvas = GetComponentInChildren<Canvas>(true);
if (canvas)
{
//把自身Cavas设定到最前方
var v = FindObjectsOfType<Canvas>().Max((item) => item.sortingOrder);//场景最前方Canvas的sortingOrder值
if (canvas.sortingOrder < v)
canvas.sortingOrder = ++v;
isInit = true;
}
}
}
public void Trigger(Vector3 pos)
{
TryInit();
if (uvAnim)
{
uvAnim.transform.position = pos;
uvAnim.Trigger();
}
}
}
新建一个Canvas,简单设置一下即可: