残影特效在网上有很多例子,比如这个,我参考着自己整合了一下,算是整合了一个比较完整且特别简单易用的出来,只需要一个脚本挂上去无需任何设定就能用。

这里只针对SkinnedMeshRenderer的网格(也就是带蒙皮的网格)残影,主要原理是根据设定的间隔时间连续的截取当前SkinnedMeshRenderer的网格数据并使用Graphics.DrawMesh画出网格。

一、首先是我们的残影类,为了能及时的Destroy,所以它最好派生至Object:

class AfterImage : Object
{
//残影网格
public Mesh _Mesh;
//残影纹理
public Material _Material;
//残影位置
public Matrix4x4 _Matrix;
//残影透明度
public float _Alpha;
//残影启动时间
public float _StartTime;
//残影保留时间
public float _Duration; public AfterImage(Mesh mesh, Material material, Matrix4x4 matrix4x4, float alpha, float startTime, float duration)
{
_Mesh = mesh;
_Material = material;
_Matrix = matrix4x4;
_Alpha = alpha;
_StartTime = startTime;
_Duration = duration;
}
}

属性描述:残影从创建之时起便记录《残影启动时间》,当其生命周期达到或者超过了设定的《残影保留时间》时,该残影即被清除;《残影网格》为残影创建之时从SkinnedMeshRenderer截取而来,保留有当前SkinnedMeshRenderer的网格数据,并依据设定的《残影纹理》在《残影位置》以《残影透明度》DrawMesh。

二、我们再定义一个残影特效类来管理残影:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 残影特效
/// </summary>
public class AfterImageEffects : MonoBehaviour { //开启残影
public bool _OpenAfterImage; //残影颜色
public Color _AfterImageColor = Color.black;
//残影的生存时间
public float _SurvivalTime = 1;
//生成残影的间隔时间
public float _IntervalTime = 0.2f;
private float _Time = 0;
//残影初始透明度
[Range(0.1f, 1.0f)]
public float _InitialAlpha = 1.0f; private List<AfterImage> _AfterImageList;
private SkinnedMeshRenderer _SkinnedMeshRenderer; void Awake () {
_AfterImageList = new List<AfterImage>();
_SkinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}
void Update () {
if (_OpenAfterImage && _AfterImageList != null)
{
if (_SkinnedMeshRenderer == null)
{
_OpenAfterImage = false;
return;
} _Time += Time.deltaTime;
//生成残影
CreateAfterImage();
//刷新残影
UpdateAfterImage();
}
}
}

属性描述:《残影的生存时间》为每个残影从创建开始到销毁经历的时间,《生成残影的间隔时间》为残影创建后到下一个残影创建的时间,每个残影都会从《初始透明度》逐渐变化到0透明度并销毁。

生成残影:

/// <summary>
/// 生成残影
/// </summary>
void CreateAfterImage()
{
//生成残影
if (_Time >= _IntervalTime)
{
_Time = 0; Mesh mesh = new Mesh();
_SkinnedMeshRenderer.BakeMesh(mesh); Material material = new Material(_SkinnedMeshRenderer.material);
SetMaterialRenderingMode(material, RenderingMode.Fade); _AfterImageList.Add(new AfterImage(
mesh,
material,
transform.localToWorldMatrix,
_InitialAlpha,
Time.realtimeSinceStartup,
_SurvivalTime));
}
}

刷新残影:

/// <summary>
/// 刷新残影
/// </summary>
void UpdateAfterImage()
{
//刷新残影,根据生存时间销毁已过时的残影
for (int i = 0; i < _AfterImageList.Count; i++)
{
float _PassingTime = Time.realtimeSinceStartup - _AfterImageList[i]._StartTime; if (_PassingTime > _AfterImageList[i]._Duration)
{
_AfterImageList.Remove(_AfterImageList[i]);
Destroy(_AfterImageList[i]);
continue;
} if (_AfterImageList[i]._Material.HasProperty("_Color"))
{
_AfterImageList[i]._Alpha *= (1 - _PassingTime / _AfterImageList[i]._Duration);
_AfterImageColor.a = _AfterImageList[i]._Alpha;
_AfterImageList[i]._Material.SetColor("_Color", _AfterImageColor);
} Graphics.DrawMesh(_AfterImageList[i]._Mesh, _AfterImageList[i]._Matrix, _AfterImageList[i]._Material, gameObject.layer);
}
}

残影存在透明通道,所以必须要设置纹理的渲染模式为fade模式:

/// <summary>
/// 设置纹理渲染模式
/// </summary>
void SetMaterialRenderingMode(Material material, RenderingMode renderingMode)
{
switch (renderingMode)
{
case RenderingMode.Opaque:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case RenderingMode.Cutout:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
case RenderingMode.Fade:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case RenderingMode.Transparent:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
}
}

三、效果图如下:

四、我将完整的源码贴一遍,只需要新建一个脚本AfterImageEffects,复制以下源码到其中,然后挂在有SkinnedMeshRenderer组件的模型上,并勾选OpenAfterImage,运行便可以看到效果:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 残影特效
/// </summary>
public class AfterImageEffects : MonoBehaviour { //开启残影
public bool _OpenAfterImage; //残影颜色
public Color _AfterImageColor = Color.black;
//残影的生存时间
public float _SurvivalTime = 1;
//生成残影的间隔时间
public float _IntervalTime = 0.2f;
private float _Time = 0;
//残影初始透明度
[Range(0.1f, 1.0f)]
public float _InitialAlpha = 1.0f; private List<AfterImage> _AfterImageList;
private SkinnedMeshRenderer _SkinnedMeshRenderer; void Awake () {
_AfterImageList = new List<AfterImage>();
_SkinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}
void Update () {
if (_OpenAfterImage && _AfterImageList != null)
{
if (_SkinnedMeshRenderer == null)
{
_OpenAfterImage = false;
return;
} _Time += Time.deltaTime;
//生成残影
CreateAfterImage();
//刷新残影
UpdateAfterImage();
}
}
/// <summary>
/// 生成残影
/// </summary>
void CreateAfterImage()
{
//生成残影
if (_Time >= _IntervalTime)
{
_Time = 0; Mesh mesh = new Mesh();
_SkinnedMeshRenderer.BakeMesh(mesh); Material material = new Material(_SkinnedMeshRenderer.material);
SetMaterialRenderingMode(material, RenderingMode.Fade); _AfterImageList.Add(new AfterImage(
mesh,
material,
transform.localToWorldMatrix,
_InitialAlpha,
Time.realtimeSinceStartup,
_SurvivalTime));
}
}
/// <summary>
/// 刷新残影
/// </summary>
void UpdateAfterImage()
{
//刷新残影,根据生存时间销毁已过时的残影
for (int i = 0; i < _AfterImageList.Count; i++)
{
float _PassingTime = Time.realtimeSinceStartup - _AfterImageList[i]._StartTime; if (_PassingTime > _AfterImageList[i]._Duration)
{
_AfterImageList.Remove(_AfterImageList[i]);
Destroy(_AfterImageList[i]);
continue;
} if (_AfterImageList[i]._Material.HasProperty("_Color"))
{
_AfterImageList[i]._Alpha *= (1 - _PassingTime / _AfterImageList[i]._Duration);
_AfterImageColor.a = _AfterImageList[i]._Alpha;
_AfterImageList[i]._Material.SetColor("_Color", _AfterImageColor);
} Graphics.DrawMesh(_AfterImageList[i]._Mesh, _AfterImageList[i]._Matrix, _AfterImageList[i]._Material, gameObject.layer);
}
}
/// <summary>
/// 设置纹理渲染模式
/// </summary>
void SetMaterialRenderingMode(Material material, RenderingMode renderingMode)
{
switch (renderingMode)
{
case RenderingMode.Opaque:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = -1;
break;
case RenderingMode.Cutout:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.EnableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 2450;
break;
case RenderingMode.Fade:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.EnableKeyword("_ALPHABLEND_ON");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
case RenderingMode.Transparent:
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.DisableKeyword("_ALPHATEST_ON");
material.DisableKeyword("_ALPHABLEND_ON");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
material.renderQueue = 3000;
break;
}
}
}
public enum RenderingMode
{
Opaque,
Cutout,
Fade,
Transparent,
}
class AfterImage : Object
{
//残影网格
public Mesh _Mesh;
//残影纹理
public Material _Material;
//残影位置
public Matrix4x4 _Matrix;
//残影透明度
public float _Alpha;
//残影启动时间
public float _StartTime;
//残影保留时间
public float _Duration; public AfterImage(Mesh mesh, Material material, Matrix4x4 matrix4x4, float alpha, float startTime, float duration)
{
_Mesh = mesh;
_Material = material;
_Matrix = matrix4x4;
_Alpha = alpha;
_StartTime = startTime;
_Duration = duration;
}
}

Unity角色残影特效的更多相关文章

  1. Unity运动残影技能

    残影实现: 1.List<DrawMesh> list,此list中包含某一帧动画模型网格.材质 2.每过一段时间就将运动物体的模型add到list中(优化:未实现,网格合并) 3.Lat ...

  2. cocos2dx - shader实现任意动画的残影效果

    本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制 这里先看下最终效果:                      这里分别实现了灰度效果及残影的效果. 一.绘制基类 这 ...

  3. Unity3d 残影效果(狂拽炫酷叼炸天)

    效果图,真的很叼啊 我根据别人的改进了一版,支持MeshFilter上的Mesh(需要确保Mesh的Read/Write是开启的否则不能正常工作) 非常感谢原作者给提供思路.http://blog.c ...

  4. Unity Shader : Ghost(残影) v1

    前阵子组长给我提了个需求,要实现角色人物的残影.我百度google了一下,发现可以用两种方式实现这个效果:1.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染.2. 通过相 ...

  5. Win7去除桌面残影的方法

    用户升级到Win7系统后使用正常,就是系统桌面会留有残影,怎么样也去不掉,影响用户的使用,那么要如何将这些残影去掉呢?可从计算机属性中进行相关配置. 解决方法 一.在计算机面板上,右键点击“计算机”, ...

  6. as3如何做出残影效果

    在页游中,时不时能看到人物做一些快速移动动作如冲刺时,有残影效果,强化了画面表现.实际人肉眼之所以能看到残影的效果,是因为观察到的物体会在人视线中残留几十毫秒时间,当运动物体运动太快时,人肉眼所见未能 ...

  7. Unity3D手游开发日记(8) - 运动残影效果

    2D游戏的残影很简单,美术做序列帧图片就行了,那么3D游戏的残影美术做不了,得靠程序员动态创建模型来处理. 实现原理也很简单: 1.间隔一定时间创建一个残影模型 GameObject go = Gam ...

  8. HDOJ(HDU) 2153 仙人球的残影(谜一样的题、、、)

    Problem Description 在美丽的HDU,有一名大三的同学,他的速度是众所周知的,跑100米仅仅用了2秒47,在他跑步过程中会留下残影的哎,大家很想知道他是谁了吧,他叫仙人球,既然名字这 ...

  9. Unity3D-Shader-人物残影效果

    [旧博客转移 - 2016年1月7日 00:24 ] 前面的话 上一篇讲了一下人物边缘发光效果,链接: Unity-ShaderLab-实现X光效果,这次我们利用这个Shader来实现人物残影效果 先 ...

随机推荐

  1. C#生成MD5码

    /// <summary> /// 获取文件的MD5码 /// </summary> /// <param name="fileName">传入 ...

  2. java中抽象类和接口之间的异同点

      抽象类 接口 声明方式 abstratc class ClassName interface ClassName 包含内容 构造方法,普通方法,抽象方法.static方法 .变量常量 全局常量.抽 ...

  3. [LeetCode] Set Mismatch 设置不匹配

    The set S originally contains numbers from 1 to n. But unfortunately, due to the data error, one of ...

  4. 机器学习技法:02 Dual Support Vector Machine

    Roadmap Motivation of Dual SVM Lagrange Dual SVM Solving Dual SVM Messages behind Dual SVM Summary

  5. 各种电脑进入BIOS快捷键

    组装机主板 品牌笔记本 品牌台式机 主板品牌 启动按键 笔记本品牌 启动按键 台式机品牌 启动按键 华硕主板 F8 联想笔记本 F12 联想台式机 F12 技嘉主板 F12 宏基笔记本 F12 惠普台 ...

  6. [HNOI2014]世界树

    题目描述 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持续运转的根本基 ...

  7. 【BZOJ1026】【SCOI2009】windy数

    Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? In ...

  8. FZU 2158

    在密室逃脱游戏中,大家被困在一个密室中,为了逃出密室,需要找到正确的数字密码,于是大家分头行动,分别找到了密码的子序列,而后大家将得到的线索集中整理分析,大家想知道密码最少是多少位.  Input 第 ...

  9. hdu 5464(dp)

    题意: 给你n个数,要求选一些数(可以不选),把它们加起来,使得和恰好是p的倍数(0也是p的倍数),求方案数. - - 心好痛,又没想到动规 #include <stdio.h> #inc ...

  10. URI与URL

    为了区分URI与URL,我们要引入URN URI = Universal Resource Identifier 统一资源标志符URL = Universal Resource Locator 统一资 ...