Tweener.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using UnityEngine;
  2. using UnityEngine.Events;
  3. namespace WXB
  4. {
  5. public class Tweener
  6. {
  7. public enum Method
  8. {
  9. Linear,
  10. EaseIn,
  11. EaseOut,
  12. EaseInOut,
  13. BounceIn,
  14. BounceOut,
  15. }
  16. public enum Style
  17. {
  18. Once,
  19. Loop,
  20. PingPong,
  21. }
  22. public Method method = Method.Linear;
  23. public Style style = Style.Once;
  24. public float duration = 1f;
  25. float mDuration = 0f;
  26. float mAmountPerDelta = 1000f;
  27. float mFactor = 0f;
  28. /// <summary>
  29. /// Amount advanced per delta time.
  30. /// </summary>
  31. public float amountPerDelta
  32. {
  33. get
  34. {
  35. if (duration == 0f) return 1000f;
  36. if (mDuration != duration)
  37. {
  38. mDuration = duration;
  39. mAmountPerDelta = Mathf.Abs(1f / duration) * Mathf.Sign(mAmountPerDelta);
  40. }
  41. return mAmountPerDelta;
  42. }
  43. }
  44. /// <summary>
  45. /// Tween factor, 0-1 range.
  46. /// </summary>
  47. public float tweenFactor { get { return mFactor; } set { mFactor = Mathf.Clamp01(value); } }
  48. public void Update(float delta)
  49. {
  50. // Advance the sampling factor
  51. mFactor += (duration == 0f) ? 1f : amountPerDelta * delta;
  52. // Loop style simply resets the play factor after it exceeds 1.
  53. if (style == Style.Loop)
  54. {
  55. if (mFactor > 1f)
  56. {
  57. mFactor -= Mathf.Floor(mFactor);
  58. }
  59. }
  60. else if (style == Style.PingPong)
  61. {
  62. // Ping-pong style reverses the direction
  63. if (mFactor > 1f)
  64. {
  65. mFactor = 1f - (mFactor - Mathf.Floor(mFactor));
  66. mAmountPerDelta = -mAmountPerDelta;
  67. }
  68. else if (mFactor < 0f)
  69. {
  70. mFactor = -mFactor;
  71. mFactor -= Mathf.Floor(mFactor);
  72. mAmountPerDelta = -mAmountPerDelta;
  73. }
  74. }
  75. // If the factor goes out of range and this is a one-time tweening operation, disable the script
  76. if ((style == Style.Once) && (duration == 0f || mFactor > 1f || mFactor < 0f))
  77. {
  78. mFactor = Mathf.Clamp01(mFactor);
  79. Sample(mFactor, true);
  80. }
  81. else
  82. {
  83. Sample(mFactor, false);
  84. }
  85. }
  86. /// <summary>
  87. /// Sample the tween at the specified factor.
  88. /// </summary>
  89. public void Sample(float factor, bool isFinished)
  90. {
  91. // Calculate the sampling value
  92. float val = Mathf.Clamp01(factor);
  93. if (method == Method.EaseIn)
  94. {
  95. val = 1f - Mathf.Sin(0.5f * Mathf.PI * (1f - val));
  96. }
  97. else if (method == Method.EaseOut)
  98. {
  99. val = Mathf.Sin(0.5f * Mathf.PI * val);
  100. }
  101. else if (method == Method.EaseInOut)
  102. {
  103. const float pi2 = Mathf.PI * 2f;
  104. val = val - Mathf.Sin(val * pi2) / pi2;
  105. }
  106. else if (method == Method.BounceIn)
  107. {
  108. val = BounceLogic(val);
  109. }
  110. else if (method == Method.BounceOut)
  111. {
  112. val = 1f - BounceLogic(1f - val);
  113. }
  114. if (OnUpdate != null)
  115. OnUpdate(val, isFinished);
  116. }
  117. /// <summary>
  118. /// Main Bounce logic to simplify the Sample function
  119. /// </summary>
  120. float BounceLogic(float val)
  121. {
  122. if (val < 0.363636f) // 0.363636 = (1/ 2.75)
  123. {
  124. val = 7.5685f * val * val;
  125. }
  126. else if (val < 0.727272f) // 0.727272 = (2 / 2.75)
  127. {
  128. val = 7.5625f * (val -= 0.545454f) * val + 0.75f; // 0.545454f = (1.5 / 2.75)
  129. }
  130. else if (val < 0.909090f) // 0.909090 = (2.5 / 2.75)
  131. {
  132. val = 7.5625f * (val -= 0.818181f) * val + 0.9375f; // 0.818181 = (2.25 / 2.75)
  133. }
  134. else
  135. {
  136. val = 7.5625f * (val -= 0.9545454f) * val + 0.984375f; // 0.9545454 = (2.625 / 2.75)
  137. }
  138. return val;
  139. }
  140. /// <summary>
  141. /// Manually activate the tweening process, reversing it if necessary.
  142. /// </summary>
  143. public void Play(bool forward)
  144. {
  145. mAmountPerDelta = Mathf.Abs(amountPerDelta);
  146. if (!forward) mAmountPerDelta = -mAmountPerDelta;
  147. }
  148. /// <summary>
  149. /// Manually reset the tweener's state to the beginning.
  150. /// If the tween is playing forward, this means the tween's start.
  151. /// If the tween is playing in reverse, this means the tween's end.
  152. /// </summary>
  153. public void ResetToBeginning()
  154. {
  155. mFactor = (amountPerDelta < 0f) ? 1f : 0f;
  156. Sample(mFactor, false);
  157. }
  158. /// <summary>
  159. /// Manually start the tweening process, reversing its direction.
  160. /// </summary>
  161. public void Toggle()
  162. {
  163. if (mFactor > 0f)
  164. {
  165. mAmountPerDelta = -amountPerDelta;
  166. }
  167. else
  168. {
  169. mAmountPerDelta = Mathf.Abs(amountPerDelta);
  170. }
  171. }
  172. /// <summary>
  173. /// Actual tweening logic should go here.
  174. /// </summary>
  175. public System.Action<float, bool> OnUpdate;
  176. }
  177. }