ProjectorTextureAnimation.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. namespace Assets.Scripts.Utils
  5. {
  6. [RequireComponent(typeof(Projector))]
  7. internal sealed class ProjectorTextureAnimation : MonoBehaviour
  8. {
  9. public int TilesX = 4;
  10. public int TilesY = 4;
  11. public float Fps = 30;
  12. public AnimationCurve FrameOverTime = AnimationCurve.Linear(0, 1, 1, 1);
  13. private Projector _projector;
  14. private Material _projectorMaterial;
  15. private Material _originalMaterial;
  16. private float _animationLifeTime;
  17. private int _index;
  18. private int _countOfTextures, _currentNumOfTexture;
  19. private bool _isStarted;
  20. private bool _isCanceled;
  21. private float _animationStartTime;
  22. private void Start()
  23. {
  24. _projector = GetComponent<Projector>();
  25. if (_projector == null)
  26. throw new InvalidOperationException("Could not get projector");
  27. _animationLifeTime = TilesX * TilesY / Fps;
  28. _index = TilesX - 1;
  29. _countOfTextures = TilesY * TilesX;
  30. Play();
  31. }
  32. private void Play()
  33. {
  34. if (_isStarted)
  35. return;
  36. if (_projector == null || _projector.material == null)
  37. return;
  38. _originalMaterial = _projector.material;
  39. _projectorMaterial = Instantiate(_projector.material);
  40. _projector.material = _projectorMaterial;
  41. if (_originalMaterial == null)
  42. return;
  43. var offset = Vector3.zero;
  44. var size = new Vector2(1f / TilesX, 1f / TilesY);
  45. _projectorMaterial.SetTextureScale("_MainTex", size);
  46. _projectorMaterial.SetTextureOffset("_MainTex", offset);
  47. _isStarted = true;
  48. StartCoroutine(UpdateCorutine());
  49. }
  50. private IEnumerator UpdateCorutine()
  51. {
  52. _animationStartTime = Time.time;
  53. while (!_isCanceled)
  54. {
  55. UpdateFrame();
  56. var frameTime = (Time.time - _animationStartTime) / _animationLifeTime;
  57. var currentSpeedFps = FrameOverTime.Evaluate(Mathf.Clamp01(frameTime));
  58. yield return new WaitForSeconds(1f / (Fps * currentSpeedFps));
  59. }
  60. }
  61. private void UpdateFrame()
  62. {
  63. ++_currentNumOfTexture;
  64. ++_index;
  65. if (_index >= _countOfTextures)
  66. _index = 0;
  67. if (_currentNumOfTexture == _countOfTextures)
  68. {
  69. _animationStartTime = Time.time;
  70. _currentNumOfTexture = 0;
  71. }
  72. var offset = new Vector2((float)_index / TilesX - (int)(_index / TilesX), 1 - (int)(_index / TilesX) / (float)TilesY);
  73. if (_projector != null)
  74. _projectorMaterial.SetTextureOffset("_MainTex", offset);
  75. }
  76. private void Stop()
  77. {
  78. _isStarted = false;
  79. _isCanceled = true;
  80. StopAllCoroutines();
  81. _projector.material = _originalMaterial;
  82. //_projectorMaterial.SetTextureScale("_MainTex", new Vector2(1, 1));
  83. //_projectorMaterial.SetTextureOffset("_MainTex", new Vector2(0, 0));
  84. }
  85. private void OnEnable()
  86. {
  87. Play();
  88. }
  89. private void OnDisable()
  90. {
  91. Stop();
  92. }
  93. private void OnDestroy()
  94. {
  95. Stop();
  96. }
  97. }
  98. }