UvAnimation.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. namespace Assets.Scripts.Utils
  5. {
  6. internal class UvAnimation : MonoBehaviour
  7. {
  8. public int TilesX = 4;
  9. public int TilesY = 4;
  10. public float Fps = 30;
  11. public int StartFrameOffset;
  12. public bool IsLoop = true;
  13. public float StartDelay = 0;
  14. public bool IsReverse;
  15. public bool IsBump;
  16. public AnimationCurve FrameOverTime = AnimationCurve.Linear(0, 1, 1, 1);
  17. private bool _isInizialised;
  18. private int _index;
  19. private int _count, _allCount;
  20. private float _animationLifeTime;
  21. private bool _isVisible;
  22. private bool _isCorutineStarted;
  23. private Renderer _currentRenderer;
  24. private Material _instanceMaterial;
  25. private float _animationStartTime;
  26. private bool _animationStoped;
  27. private void Start()
  28. {
  29. _currentRenderer = GetComponent<Renderer>();
  30. InitDefaultVariables();
  31. _isInizialised = true;
  32. _isVisible = true;
  33. Play();
  34. }
  35. private void InitDefaultVariables()
  36. {
  37. _currentRenderer = GetComponent<Renderer>();
  38. if (_currentRenderer == null)
  39. throw new Exception("UvTextureAnimator can't get renderer");
  40. if (!_currentRenderer.enabled)
  41. _currentRenderer.enabled = true;
  42. _allCount = 0;
  43. _animationStoped = false;
  44. _animationLifeTime = TilesX * TilesY / Fps;
  45. _count = TilesY * TilesX;
  46. _index = TilesX - 1;
  47. var offset = Vector3.zero;
  48. StartFrameOffset = StartFrameOffset - (StartFrameOffset / _count) * _count;
  49. var size = new Vector2(1f / TilesX, 1f / TilesY);
  50. if (_currentRenderer != null)
  51. {
  52. _instanceMaterial = _currentRenderer.material;
  53. _instanceMaterial.SetTextureScale("_MainTex", size);
  54. _instanceMaterial.SetTextureOffset("_MainTex", offset);
  55. if (IsBump)
  56. {
  57. _instanceMaterial.SetTextureScale("_BumpMap", size);
  58. _instanceMaterial.SetTextureOffset("_BumpMap", offset);
  59. }
  60. }
  61. }
  62. private void Play()
  63. {
  64. if (_isCorutineStarted)
  65. return;
  66. if (StartDelay > 0.0001f)
  67. Invoke("PlayDelay", StartDelay);
  68. else
  69. StartCoroutine(UpdateCorutine());
  70. _isCorutineStarted = true;
  71. }
  72. private void PlayDelay()
  73. {
  74. StartCoroutine(UpdateCorutine());
  75. }
  76. private void OnEnable()
  77. {
  78. if (!_isInizialised)
  79. return;
  80. InitDefaultVariables();
  81. _isVisible = true;
  82. Play();
  83. }
  84. private void OnDisable()
  85. {
  86. _isCorutineStarted = false;
  87. _isVisible = false;
  88. StopAllCoroutines();
  89. CancelInvoke("PlayDelay");
  90. }
  91. private IEnumerator UpdateCorutine()
  92. {
  93. _animationStartTime = Time.time;
  94. while (_isVisible && (IsLoop || !_animationStoped))
  95. {
  96. if (!IsReverse)
  97. UpdateFrame();
  98. else
  99. UpdateFrameReversed();
  100. if (!IsLoop && _animationStoped)
  101. break;
  102. var frameTime = (Time.time - _animationStartTime) / _animationLifeTime;
  103. var currentSpeedFps = FrameOverTime.Evaluate(Mathf.Clamp01(frameTime));
  104. yield return new WaitForSeconds(1f / (Fps * currentSpeedFps));
  105. }
  106. _isCorutineStarted = false;
  107. //currentRenderer.enabled = false;
  108. }
  109. private void UpdateFrame()
  110. {
  111. ++_allCount;
  112. ++_index;
  113. if (_index >= _count)
  114. _index = 0;
  115. if (_count == _allCount)
  116. {
  117. _animationStartTime = Time.time;
  118. _allCount = 0;
  119. _animationStoped = true;
  120. }
  121. var offset = new Vector2((float)_index / TilesX - (int)(_index / TilesX), 1 - (int)(_index / TilesX) / (float)TilesY);
  122. if (_currentRenderer != null)
  123. {
  124. _instanceMaterial.SetTextureOffset("_MainTex", offset);
  125. if (IsBump)
  126. _instanceMaterial.SetTextureOffset("_BumpMap", offset);
  127. }
  128. }
  129. private void UpdateFrameReversed()
  130. {
  131. --_allCount;
  132. --_index;
  133. if (_index <= 0)
  134. _index = _count;
  135. if (_count == _allCount)
  136. {
  137. _animationStartTime = Time.time;
  138. _allCount = 0;
  139. _animationStoped = true;
  140. }
  141. var offset = new Vector2((float)_index / TilesX - (int)(_index / TilesX), 1 - (int)(_index / TilesX) / (float)TilesY);
  142. if (_currentRenderer != null)
  143. {
  144. _instanceMaterial.SetTextureOffset("_MainTex", offset);
  145. if (IsBump)
  146. _instanceMaterial.SetTextureOffset("_BumpMap", offset);
  147. }
  148. }
  149. private void OnDestroy()
  150. {
  151. if (_instanceMaterial != null)
  152. {
  153. Destroy(_instanceMaterial);
  154. _instanceMaterial = null;
  155. }
  156. }
  157. }
  158. }