Unity3D-Shader-人物残影效果 [

原文 : http://www.manew.com/thread-106655-1-1.html


这次我们利用人物边缘发光效果来实现人物残影效果

  先来看一下效果  →_→

Unity3D-Shader-人物残影效果 [

  大概的原理
  1、创建残影:拷贝人物当前Mesh数据作为残影,用MeshFilter+MeshRenderer渲染出来
  2、残影有生命周期、创建间隔:残影从创建到慢慢消失的过程,这里采用透明度淡出
  3、使用X光Shader
[C#] 纯文本查看 复制代码
 
1
Mesh mesh = new Mesh ();
meshRender[i].BakeMesh(mesh);


  BakeMesh拷贝网格
  拷贝网格很简单,调用SkinnedMeshRenderer的BakeMesh方法
  用MeshFilter跟MeshRenderer渲染网格
[C#] 纯文本查看 复制代码
 
1
2
3
4
5
6
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哦
  完整代码
[C#] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
[C#] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);
        }
         
    }
}


  最后的话
  这篇就写完啦,这种实现方式的优点就是残影可以实时捕捉动作,比较动态。缺点是比较消耗性能,频繁创建网格,相当于要多渲染那么多个人物。
来源:博客“那个少年”