summaryrefslogtreecommitdiff
path: root/Assets/Scripts/Effects/CharacterGhostEffect.cs
blob: d422c0a706fe68e655642b23aae5d7009ff27699 (plain)
1
2
3
4
5
6
7
8
9
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharacterGhostEffect : EffectHandler
{
	[Tooltip("目标skinMeshRenderer")]
	public SkinnedMeshRenderer m_Renderer;

	[Tooltip("如果mesh包含多个submesh,需要每个submesh单独设置一个材质")]
	public Material[] Materials;

	[Tooltip("Submesh是否使用同一个材质")]
	public bool SubmeshShareMaterial;

	[Tooltip("使用范围内的submesh")]
	public bool UseRangedSubmesh;

	[Tooltip("Submesh索引范围")]
	public Vector2Int SubmeshRange; 

	[Tooltip("是否开启残影效果")]
	public bool IsEnable;

	[Tooltip("残影生成的时间间隔")]
	public float Interval = 0.1f;

	[Tooltip("残影的生存时间")]
	public float LifeTime = 0.5f;

	private float m_Time = 0;
	private List<GhostSnapshot> m_Ghosts = new List<GhostSnapshot>();
 	
	void Update()
	{
		//if (!IsEnable)
		//{
		//	if (m_Ghosts.Count > 0)
		//		UpdateGhost(); // destroy ghosts
		//	return;
		//}

		if (m_Ghosts == null || m_Renderer == null || Materials == null || Materials.Length == 0)
		{
			IsEnable = false;
			return;
		}

		m_Time += Time.deltaTime;

		//if(IsEnable)
		//	CreateGhost();

		UpdateGhost();
		DrawGhost();
	}

	public void CreateGhost()
	{
		if(m_Time >= Interval)
		{
			m_Time -= Interval;

			Mesh mesh = new Mesh();
			m_Renderer.BakeMesh(mesh);

			Matrix4x4 mat = m_Renderer.localToWorldMatrix;

			m_Ghosts.Add(new GhostSnapshot(mesh, mat, Time.realtimeSinceStartup, LifeTime));
		}
	}

	void UpdateGhost()
	{
		for(int i = m_Ghosts.Count - 1; i >= 0 ; --i)
		{
			GhostSnapshot ghost = m_Ghosts[i];
			float passTime = Time.realtimeSinceStartup - ghost.startTime;

			if (passTime > ghost.lifeTime)
			{
				m_Ghosts.Remove(ghost);
				Destroy(ghost);
				continue;
			}
		}
	}

	void DrawGhost()
	{
		for(int i = 0; i < m_Ghosts.Count; ++ i)
		{
			GhostSnapshot ghost = m_Ghosts[i];
			int start = 0, end = ghost.mesh.subMeshCount - 1;
			if(UseRangedSubmesh)
			{
				start = SubmeshRange.x;
				end = SubmeshRange.y;
			}
			for (int j = start; j <= end; ++j)
			{
				Material material;
				if (SubmeshShareMaterial)
					material = Materials[0];
				else
					material = Materials[j - start];
				Graphics.DrawMesh(ghost.mesh, ghost.matrix, material, gameObject.layer, null, j);
			}
		}
	}
}

class GhostSnapshot : Object
{
	public Mesh mesh;
	public Matrix4x4 matrix;
	public float startTime;
	public float lifeTime;

	public GhostSnapshot(Mesh mesh, Matrix4x4 mat, float startTime, float lifeTime)
	{
		this.mesh = mesh;
		this.matrix = mat;
		this.startTime = startTime;
		this.lifeTime = lifeTime;
	}
}