【旧博客转移 - 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); } } }
最后的话
这篇就写完啦,这种实现方式的优点就是残影可以实时捕捉动作,比较动态。缺点是比较消耗性能,频繁创建网格,相当于要多渲染那么多个人物。
如果有好的的优化思路,欢迎在下面评论