版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
一.最近学习unity看到一个关于人物残影的实现过程,在这里记一下,大概原理就是
通过获取人物的SkinnedMeshRenderer组件,然后将其中重要的材质和Mesh赋值给新创建的Gameobject物体上,然后设置淡出效果,按生存周期销毁gameobject就好了;
详细的看代码吧;
为人物添加脚本:(脚本中设有注释就不多说了)
代码语言:javascript复制<span style="font-size:18px;">using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DestroyShadow : MonoBehaviour {
public float interval = 0.1f; //残影的时间间隔;
public float lifeCycle = 2f; //残影的生存周期
float lastCombineTime = 0.0f; //上次组合时间;
MeshFilter[] meshFilters = null;
SkinnedMeshRenderer[] skinnedMeshRenderers = null;
List<GameObject> objs = new List<GameObject>();
// Use this for initialization
void Start () {
meshFilters = gameObject.GetComponentsInChildren<MeshFilter>();
skinnedMeshRenderers = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
}
void OnDisable()
{
foreach (GameObject go in objs)
{
DestroyImmediate(go);
}
objs.Clear();
objs = null;
}
// Update is called once per frame
void Update () {
if (Time.time - lastCombineTime > interval)
{
lastCombineTime = Time.time;
for (int i = 0; skinnedMeshRenderers != null && i < skinnedMeshRenderers.Length; i)//遍历skinedMeshRenderers
{
Mesh mesh = new Mesh();
skinnedMeshRenderers[i].BakeMesh(mesh); //烘焙到新生成的mesh
GameObject go = new GameObject(); //生成新的gameobject
go.hideFlags = HideFlags.HideAndDontSave; //设置go的属性隐藏不保存
MeshFilter meshFilter = go.AddComponent<MeshFilter>(); //添加meshFilter组件
meshFilter.mesh = mesh; //将新添加的meshFilter设置为Mesh;
MeshRenderer meshRender = go.AddComponent<MeshRenderer>(); //添加meshRenderer组件;
meshRender.material = skinnedMeshRenderers[i].material; //将新添加的MeshRenderer的材质设置为获取到的材质;
InitFadeInObj(go, skinnedMeshRenderers[i].transform.position,
skinnedMeshRenderers[i].transform.rotation, lifeCycle); //淡入淡出
}
for (int i = 0; meshFilters != null && meshFilters.Length > 0; i)
{
GameObject go = Instantiate(meshFilters[i].gameObject) as GameObject;
InitFadeInObj(go, meshFilters[i].transform.position,
meshFilters[i].transform.rotation, lifeCycle); //新生成GameObject并且将其设置淡入淡出
}
}
}
private void InitFadeInObj(GameObject go, Vector3 position, Quaternion rotation, float lifeCycle)
{
go.hideFlags = HideFlags.HideAndDontSave; //设置go的属性隐藏不保存;
go.transform.position = position;
go.transform.rotation = rotation;
FindInOut fi = go.AddComponent<FindInOut>();//添加FadInOut脚本
fi.lifeStytle = lifeCycle;//复制生命周期
objs.Add(go);//放入列表中
}
}</span>
二.在写个脚本,此脚本无需绑定;(由于对Shader不太了解,所以用的都是Unity自带的Shader,没有淡出效果,如果需要的话直接改改就好了)
代码语言:javascript复制<span style="font-size:18px;">using UnityEngine;
using System.Collections;
public class FindInOut : MonoBehaviour {
public float lifeStytle = 2f;
float startTime;
Material mat = null;
// Use this for initialization
void Start () {
startTime = Time.time; //得到启动时间
MeshRenderer meshRender = GetComponent<MeshRenderer>();
if (!meshRender || !meshRender.material)
{
base.enabled = false; //为空的话禁用;
}
else {
mat = meshRender.material; //得到材质;
ReplaceShader(); //替换Shader
}
}
// Update is called once per frame
void Update () {
float time = Time.time - startTime; //获取运行时间;
if (time > lifeStytle)
{
DestroyImmediate(gameObject);
}
else {
float remainderTime = lifeStytle - time; //得到剩余时间
if (mat)
{
//if(mat.HasProperty("_Color")) 得到mat中是否有这个属性
Color col = mat.GetColor("Tint"); //得到材质中的shader中的_Color颜色
col.a = remainderTime;//设置Alpha(剩余时间越小 Alpha值越小)
mat.SetColor("Tint", col);//将修改后的颜色设置回去
col = mat.GetColor("Tint");//原理同上
col.a = remainderTime;
mat.SetColor("Tint", col);
}
}
}
private void ReplaceShader()
{
if (mat.shader.name.Equals("Unlit/Transparent"))//检查当前shader名字是否是“ ”
{
mat.shader = Shader.Find("Particles/Additive");//如果是的话 替换shader
}
else if (mat.shader.name.Equals("Sprites/Default"))
{
mat.shader = Shader.Find("Particles/Additive(Soft)");
}
else
{
Debug.LogError("Can't find target shader");
}
}
}
</span>
上面的方法太消耗性能了,下面更新下最近新学的简单点的
代码语言:javascript复制using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShowShadowTail : MonoBehaviour {
public float fadeSpeed = 3;
public float createSpeed = 5;
private float previousTime = 0;
private SkinnedMeshRenderer []meshRender;
private MeshFilter []meshFilter;
void Awake()
{
meshRender = this.GetComponentsInChildren<SkinnedMeshRenderer>();
meshFilter = this.GetComponentsInChildren<MeshFilter>();
}
struct MeshInfo {
public Mesh mesh;
public Matrix4x4 _matrix_PR; //存儲位置和旋转角度;
public Material material;
};
List<MeshInfo> meshInfoList = new List<MeshInfo>();
void Update () {
foreach(MeshInfo meshInfo in meshInfoList)
{
Graphics.DrawMesh(meshInfo.mesh,meshInfo._matrix_PR,meshInfo.material,gameObject.layer);
float timer= meshInfo.material.GetFloat("_Alpha") - Time.deltaTime* fadeSpeed;
meshInfo.material.SetFloat("_Alpha",timer>0?timer:0);
if(meshInfo.material.GetFloat("_Alpha")<0)
{
meshInfoList.Remove(meshInfo);
}
}
if(Time.time-previousTime>createSpeed*Time.deltaTime)
{
previousTime = Time.time;
foreach (SkinnedMeshRenderer meshRender in meshRender)
{
Mesh mesh = new Mesh();
meshRender.BakeMesh(mesh);
MeshInfo meshInfo = new MeshInfo();
meshInfo.mesh = mesh;
meshInfo._matrix_PR = meshRender.localToWorldMatrix;
meshInfo.material = new Material(Shader.Find("Unlit/GrabGlass"));
meshInfoList.Add(meshInfo);
}
foreach (MeshFilter filter in meshFilter)
{
MeshInfo meshInfo = new MeshInfo();
meshInfo.mesh = filter.mesh;
meshInfo._matrix_PR = filter.transform.localToWorldMatrix;
meshInfo.material = new Material(Shader.Find("Unlit/GrabGlass"));
meshInfoList.Add(meshInfo);
}
}
}
}
最近人变懒了,只想上代码,多余的字都不想写了,唉!不足之处望指出,大家共同进步!!!