SFX_MotionCloner.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. // ReSharper disable once CheckNamespace
  4. namespace QFX.SFX
  5. {
  6. public class SFX_MotionCloner : SFX_ControlledObject
  7. {
  8. public GameObject TargetGameObject;
  9. public float CloneLifeTime = 1f;
  10. public float CloneRate = 1f;
  11. public bool ReplaceMaterialInMotion;
  12. public Material MotionMaterial;
  13. public GameObject TrailParticleSystem;
  14. public GameObject ActivateCloneParticleSystem;
  15. public GameObject FinishMotionParticleSystem;
  16. public GameObject CloneParticleSystem;
  17. public MeshRenderer MeshRenderer;
  18. public SkinnedMeshRenderer SkinnedMeshRenderer;
  19. private GameObject _activateCloneGo;
  20. private ParticleSystem _activateClonePs;
  21. private GameObject _trailGo;
  22. private ParticleSystem _trailPs;
  23. private GameObject _finishGo;
  24. private ParticleSystem _finishPs;
  25. private readonly Dictionary<Renderer, Material[]> _rendererToSharedMaterials =
  26. new Dictionary<Renderer, Material[]>();
  27. private float _time;
  28. public override void Setup()
  29. {
  30. base.Setup();
  31. if (ReplaceMaterialInMotion)
  32. {
  33. var rends = TargetGameObject.GetComponentsInChildren<Renderer>();
  34. foreach (var rend in rends)
  35. _rendererToSharedMaterials[rend] = rend.sharedMaterials;
  36. }
  37. if (ActivateCloneParticleSystem != null)
  38. {
  39. _activateCloneGo = Instantiate(ActivateCloneParticleSystem, Vector3.zero, Quaternion.identity);
  40. _activateClonePs = _activateCloneGo.GetComponent<ParticleSystem>();
  41. _activateCloneGo.SetActive(true);
  42. _activateCloneGo.transform.parent = TargetGameObject.transform;
  43. if (MeshRenderer != null)
  44. SFX_ParticleSystemMeshAttacher.Attach(_activateClonePs, MeshRenderer, 0f);
  45. else if (SkinnedMeshRenderer != null)
  46. SFX_ParticleSystemMeshAttacher.Attach(_activateClonePs, SkinnedMeshRenderer, 0f);
  47. }
  48. if (TrailParticleSystem != null)
  49. {
  50. _trailGo = Instantiate(TrailParticleSystem, Vector3.zero, Quaternion.identity);
  51. _trailPs = _trailGo.GetComponent<ParticleSystem>();
  52. _trailGo.SetActive(true);
  53. _trailGo.transform.parent = TargetGameObject.transform;
  54. if (MeshRenderer != null)
  55. SFX_ParticleSystemMeshAttacher.Attach(_trailPs, MeshRenderer, 0f);
  56. else if (SkinnedMeshRenderer != null)
  57. SFX_ParticleSystemMeshAttacher.Attach(_trailPs, SkinnedMeshRenderer, 0f);
  58. }
  59. if (FinishMotionParticleSystem != null)
  60. {
  61. _finishGo = Instantiate(FinishMotionParticleSystem, Vector3.zero, Quaternion.identity);
  62. _finishPs = _finishGo.GetComponent<ParticleSystem>();
  63. _finishGo.SetActive(true);
  64. _finishGo.transform.parent = TargetGameObject.transform;
  65. if (MeshRenderer != null)
  66. SFX_ParticleSystemMeshAttacher.Attach(_finishPs, MeshRenderer, 0f);
  67. else if (SkinnedMeshRenderer != null)
  68. SFX_ParticleSystemMeshAttacher.Attach(_finishPs, SkinnedMeshRenderer, 0f);
  69. }
  70. }
  71. public override void Run()
  72. {
  73. if (IsRunning)
  74. return;
  75. Activate();
  76. base.Run();
  77. }
  78. public override void Stop()
  79. {
  80. base.Stop();
  81. DeActivate();
  82. }
  83. public void MakeClone()
  84. {
  85. if (_activateCloneGo != null && _activateClonePs != null)
  86. {
  87. _activateCloneGo.transform.position = transform.position;
  88. _activateClonePs.Play();
  89. }
  90. var clone = Instantiate(TargetGameObject, TargetGameObject.transform.position,
  91. TargetGameObject.transform.rotation);
  92. foreach (var comp in clone.GetComponentsInChildren<Component>())
  93. if (!(comp is Renderer) && !(comp is Transform) && !(comp is MeshFilter))
  94. Destroy(comp);
  95. var cloneDestroyer = clone.AddComponent<SFX_SelfDestroyer>();
  96. cloneDestroyer.LifeTime = CloneLifeTime;
  97. cloneDestroyer.Run();
  98. if (CloneParticleSystem != null)
  99. {
  100. var go = Instantiate(CloneParticleSystem, TargetGameObject.transform.position,
  101. TargetGameObject.transform.transform.rotation);
  102. var ps = go.GetComponent<ParticleSystem>();
  103. if (MeshRenderer != null)
  104. SFX_ParticleSystemMeshAttacher.Attach(ps, MeshRenderer, 0f);
  105. else if (SkinnedMeshRenderer != null)
  106. SFX_ParticleSystemMeshAttacher.Attach(ps, SkinnedMeshRenderer, 0f);
  107. ps.gameObject.SetActive(true);
  108. ps.Play();
  109. }
  110. Destroy(clone, CloneLifeTime);
  111. }
  112. private void Activate()
  113. {
  114. _time = 0;
  115. if (ReplaceMaterialInMotion)
  116. {
  117. foreach (var originalMaterial in _rendererToSharedMaterials.Keys)
  118. {
  119. var newMaterials = new Material[originalMaterial.sharedMaterials.Length];
  120. for (int i = 0; i < newMaterials.Length; i++)
  121. newMaterials[i] = MotionMaterial;
  122. originalMaterial.sharedMaterials = newMaterials;
  123. }
  124. }
  125. if (_trailPs != null)
  126. _trailPs.Play();
  127. MakeClone();
  128. }
  129. private void DeActivate()
  130. {
  131. if (_trailPs != null)
  132. _trailPs.Stop();
  133. foreach (var originalMaterial in _rendererToSharedMaterials)
  134. originalMaterial.Key.sharedMaterials = originalMaterial.Value;
  135. if (_finishPs != null)
  136. _finishPs.Play();
  137. }
  138. private void Update()
  139. {
  140. if (Input.GetMouseButtonDown(0))
  141. Run();
  142. else if (Input.GetMouseButtonUp(0))
  143. Stop();
  144. if (!IsRunning)
  145. return;
  146. _time += Time.deltaTime;
  147. if (_time >= CloneRate)
  148. {
  149. MakeClone();
  150. _time = 0;
  151. }
  152. }
  153. private void OnDestroy()
  154. {
  155. Destroy(_activateCloneGo);
  156. Destroy(_trailGo);
  157. Destroy(_finishGo);
  158. }
  159. }
  160. }