工程截图
残影脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 残影效果 /// </summary> public class AfterimageEffect : MonoBehaviour { //是否开启效果 public bool enabledEffect = false; [SerializeField] private SkinnedMeshRenderer m_SkinnedMeshRenderer; //生成残影间隔时间 [SerializeField] private float interval = 0.2f; //残影淡出速度 [SerializeField] private float fadeOutSpeed = 1f; [Tooltip("是否只在移动时产生残影")] [SerializeField] private bool onlyMove = true; private float lastGenTime = 0; private Transform cacheTransform; private Vector3 lastPosition = Vector3.zero; private List<Afterimage> afterimageList = new List<Afterimage>(); void Awake() { cacheTransform = transform; } void Update() { for (int i = afterimageList.Count-1; i >= 0; i--) { Afterimage afterimage = afterimageList[i]; float fadeOutAlpha = Time.deltaTime * fadeOutSpeed; afterimage.FadeOutAlpha(fadeOutAlpha); if (!afterimage.lifeCycle) afterimageList.RemoveAt(i); } if (!enabledEffect) return; if (onlyMove) { //如果未移动,则不产生残影 Vector3 position = cacheTransform.position; if (Mathf.Approximately(position.x, lastPosition.x) && Mathf.Approximately(position.y, lastPosition.y) && Mathf.Approximately(position.z, lastPosition.z)) return; lastPosition = position; } if (Time.time - lastGenTime < interval) return; lastGenTime = Time.time; CreateAfterimage(); } //创建快照 public void CreateAfterimage() { Mesh mesh = new Mesh(); m_SkinnedMeshRenderer.BakeMesh(mesh); GameObject go = new GameObject(); //残影对象不显示在层级面板及场景中 go.hideFlags = HideFlags.HideAndDontSave; //设置layer层 go.layer = 8; //可选 go.transform.position = cacheTransform.position; Vector3 eulerAngles = cacheTransform.rotation.eulerAngles; //可能其他3D软件生成的Mesh采用的坐标系与Unity不一致,需要特殊处理下 Vector3 go_eulerAngles = new Vector3(eulerAngles.x-90, eulerAngles.z, eulerAngles.y); go.transform.rotation = Quaternion.Euler(go_eulerAngles); MeshFilter meshFilter = go.AddComponent<MeshFilter>(); meshFilter.mesh = mesh; MeshRenderer meshRenderer = go.AddComponent<MeshRenderer>(); int materialsLength = m_SkinnedMeshRenderer.materials.Length; meshRenderer.materials = new Material[materialsLength]; for (int i = 0; i < materialsLength; i++) { meshRenderer.materials[i] = m_SkinnedMeshRenderer.materials[i]; meshRenderer.materials[i].shader = Shader.Find("Sprites/Diffuse"); Color col = new Color(0.85f, 0.43f, 0.84f, 0.2f); meshRenderer.materials[i].SetColor("_Color", col); } Afterimage afterimage = new Afterimage(); afterimage.go = go; afterimage.meshRenderer = meshRenderer; afterimageList.Add(afterimage); } public class Afterimage { public GameObject go; public MeshRenderer meshRenderer; //生命周期 public bool lifeCycle = true; public void FadeOutAlpha(float alpha) { for (int i = 0; i < meshRenderer.materials.Length; i++) { Color color = meshRenderer.materials[i].color; color.a -= alpha; meshRenderer.materials[i].color = color; if (color.a <= 0) lifeCycle = false; } if (!lifeCycle) Destroy(); } public void Destroy() { GameObject.Destroy(go); } } }
运行效果 (这里是手动拖动角色移动,所以产生的残影间隔不一致)