首页 > Unity > [蛮牛干货] Unity3D-Shader-人物残影效果
2017
08-22

[蛮牛干货] Unity3D-Shader-人物残影效果

这次我们利用人物边缘发光效果来实现人物残影效果
先来看一下效果  →_→

[蛮牛干货] Unity3D-Shader-人物残影效果 - 第1张  | FreemanApp

大概的原理
1、创建残影:拷贝人物当前Mesh数据作为残影,用MeshFilter+MeshRenderer渲染出来
2、残影有生命周期、创建间隔:残影从创建到慢慢消失的过程,这里采用透明度淡出
3、使用X光Shader

Mesh mesh = new Mesh ();
meshRender[i].BakeMesh(mesh);

BakeMesh拷贝网格
拷贝网格很简单,调用SkinnedMeshRenderer的BakeMesh方法
用MeshFilter跟MeshRenderer渲染网格

MeshFilter filter = go.AddComponent();
filter.mesh = mesh;
 
MeshRenderer meshRen = go.AddComponent();
 
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 ();
 
        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();//控制残影消失
            item.duration = duration;
            item.deleteTime = Time.time + duration;
 
            MeshFilter filter = go.AddComponent();
            filter.mesh = mesh;
 
            MeshRenderer meshRen = go.AddComponent();
 
            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);
        }
 
    }
}

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

最后编辑:
作者:freeman
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据