【舊博客轉移 - 2016年1月7日 00:24 】
前面的話
上一篇講了一下人物邊緣發光效果,鏈接: Unity-ShaderLab-實現X光效果,這次我們利用這個Shader來實現人物殘影效果
大概的原理
- 創建殘影:拷貝人物當前Mesh數據作為殘影,用MeshFilter+MeshRenderer渲染出來
- 殘影有生命周期、創建間隔:殘影從創建到慢慢消失的過程,這里采用透明度淡出
- 使用X光Shader
Mesh mesh = new Mesh (); meshRender[i].BakeMesh(mesh);
BakeMesh拷貝網格
拷貝網格很簡單,調用SkinnedMeshRenderer的BakeMesh方法
用MeshFilter跟MeshRenderer渲染網格
MeshFilter filter = go.AddComponent<MeshFilter>(); filter.mesh = mesh; MeshRenderer meshRen = go.AddComponent<MeshRenderer>(); meshRen.material = meshRender[i].material; meshRen.material.shader = ghostShader;//設置xray效果
MeshFilter:網格過濾器用於從你的資源中獲取網格信息(Mesh)並將其傳遞到用於將其渲染到屏幕的網格渲染器當中
MeshRenderer:但是想要渲染出網格,還需要用到MeshRenderer哦
完整代碼
using UnityEngine; using System.Collections; using System.Collections.Generic; public class GhostShadow : MonoBehaviour { //持續時間 public float duration = 2f; //創建新殘影間隔 public float interval = 0.1f; //邊緣顏色強度 [Range(-1, 2)] public float Intension = 1; //網格數據 SkinnedMeshRenderer[] meshRender; //X-ray Shader ghostShader; void Start () { //獲取身上所有的Mesh meshRender = this.gameObject.GetComponentsInChildren<SkinnedMeshRenderer> (); ghostShader = Shader.Find("lijia/Xray"); } private float lastTime = 0; private Vector3 lastPos = Vector3.zero; void Update () { //人物有位移才創建殘影 if (lastPos == this.transform.position) { return; } lastPos = this.transform.position; if(Time.time - lastTime < interval){//殘影間隔時間 return; } lastTime = Time.time; if (meshRender == null) return; for (int i = 0; i < meshRender.Length; i++) { Mesh mesh = new Mesh (); meshRender[i].BakeMesh(mesh); GameObject go = new GameObject(); go.hideFlags = HideFlags.HideAndDontSave; GhostItem item = go.AddComponent<GhostItem>();//控制殘影消失 item.duration = duration; item.deleteTime = Time.time + duration; MeshFilter filter = go.AddComponent<MeshFilter>(); filter.mesh = mesh; MeshRenderer meshRen = go.AddComponent<MeshRenderer>(); meshRen.material = meshRender[i].material; meshRen.material.shader = ghostShader;//設置xray效果 meshRen.material.SetFloat("_Intension", Intension);//顏色強度傳入shader中 go.transform.localScale = meshRender[i].transform.localScale; go.transform.position = meshRender[i].transform.position; go.transform.rotation = meshRender[i].transform.rotation; item.meshRenderer = meshRen; } } }
GhostItem
using System; using UnityEngine; public class GhostItem : MonoBehaviour { //持續時間 public float duration; //銷毀時間 public float deleteTime; public MeshRenderer meshRenderer; void Update(){ float tempTime = deleteTime - Time.time; if (tempTime <= 0) {//到時間就銷毀 GameObject.Destroy (this.gameObject); } else if(meshRenderer.material){ float rate = tempTime/duration;//計算生命周期的比例 Color cal = meshRenderer.material.GetColor("_RimColor"); cal.a *= rate;//設置透明通道 meshRenderer.material.SetColor("_RimColor", cal); } } }
最后的話
這篇就寫完啦,這種實現方式的優點就是殘影可以實時捕捉動作,比較動態。缺點是比較消耗性能,頻繁創建網格,相當於要多渲染那么多個人物。
如果有好的的優化思路,歡迎在下面評論