LeanSmooth.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /**
  5. * Use these smooth methods to move one value towards another<br /><br />
  6. * <strong>Example: </strong><br />fromY = LeanSmooth.spring(fromY, followArrow.localPosition.y, ref velocityY, 1.1f);<br />
  7. * fromVec3 = LeanSmooth.damp(fromVec3, dude5Title.localPosition, ref velocityVec3, 1.1f);<br />
  8. * fromColor = LeanSmooth.damp(fromColor, dude5Title.GetComponent<Renderer>().material.color, ref velocityColor, 1.1f);<br />
  9. * Debug.Log("Smoothed y:" + fromY + " vec3:" + fromVec3 + " color:" + fromColor);<br />
  10. *
  11. * @class LeanSmooth
  12. */
  13. public class LeanSmooth {
  14. /**
  15. * <summary>Moves one value towards another (eases in and out to destination with no overshoot)</summary>
  16. *
  17. * @method LeanSmooth.damp (float)
  18. * @param {float} current:float the current value
  19. * @param {float} target:float the value we are trying to reach
  20. * @param {float} currentVelocity:float the current velocity of the value
  21. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  22. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  23. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  24. * @example
  25. * followVar = LeanSmooth.damp(followVar, destinationVar, ref followVelocity, 1.1f);\n
  26. * Debug.Log("current:"+followVar);
  27. */
  28. public static float damp(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f)
  29. {
  30. if (deltaTime < 0f)
  31. deltaTime = Time.deltaTime;
  32. smoothTime = Mathf.Max(0.0001f, smoothTime);
  33. float num = 2f / smoothTime;
  34. float num2 = num * deltaTime;
  35. float num3 = 1f / (1f + num2 + 0.48f * num2 * num2 + 0.235f * num2 * num2 * num2);
  36. float num4 = current - target;
  37. float num5 = target;
  38. if (maxSpeed > 0f)
  39. {
  40. float num6 = maxSpeed * smoothTime;
  41. num4 = Mathf.Clamp(num4, -num6, num6);
  42. }
  43. target = current - num4;
  44. float num7 = (currentVelocity + num * num4) * deltaTime;
  45. currentVelocity = (currentVelocity - num * num7) * num3;
  46. float num8 = target + (num4 + num7) * num3;
  47. if (num5 - current > 0f == num8 > num5)
  48. {
  49. num8 = num5;
  50. currentVelocity = (num8 - num5) / deltaTime;
  51. }
  52. return num8;
  53. }
  54. /**
  55. * <summary>Moves one value towards another (eases in and out to destination with no overshoot)</summary>
  56. *
  57. * @method LeanSmooth.damp (Vector3)
  58. * @param {float} current:Vector3 the current value
  59. * @param {float} target:Vector3 the value we are trying to reach
  60. * @param {float} currentVelocity:Vector3 the current velocity of the value
  61. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  62. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  63. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  64. * @example
  65. * transform.position = LeanSmooth.damp(transform.position, destTrans.position, ref followVelocity, 1.1f);\n
  66. * Debug.Log("current:"+transform.position);
  67. */
  68. public static Vector3 damp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f)
  69. {
  70. float x = damp(current.x, target.x, ref currentVelocity.x, smoothTime, maxSpeed, deltaTime);
  71. float y = damp(current.y, target.y, ref currentVelocity.y, smoothTime, maxSpeed, deltaTime);
  72. float z = damp(current.z, target.z, ref currentVelocity.z, smoothTime, maxSpeed, deltaTime);
  73. return new Vector3(x, y, z);
  74. }
  75. /**
  76. * <summary>Moves one color value towards another color (eases in and out to destination with no overshoot)</summary>
  77. *
  78. * @method LeanSmooth.damp (Color)
  79. * @param {float} current:Color the current value
  80. * @param {float} target:Color the value we are trying to reach
  81. * @param {float} currentVelocity:Color the current velocity of the value
  82. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  83. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  84. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  85. * @example
  86. * fromColor = LeanSmooth.damp(fromColor, transform.GetComponent<Renderer>().material.color, ref velocityColor, 1.1f);\n
  87. * Debug.Log("current:"+fromColor);
  88. */
  89. public static Color damp(Color current, Color target, ref Color currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f)
  90. {
  91. float r = damp(current.r, target.r, ref currentVelocity.r, smoothTime, maxSpeed, deltaTime);
  92. float g = damp(current.g, target.g, ref currentVelocity.g, smoothTime, maxSpeed, deltaTime);
  93. float b = damp(current.b, target.b, ref currentVelocity.b, smoothTime, maxSpeed, deltaTime);
  94. float a = damp(current.a, target.a, ref currentVelocity.a, smoothTime, maxSpeed, deltaTime);
  95. return new Color(r, g, b, a);
  96. }
  97. /**
  98. * <summary>Moves one value towards another (eases in and out to destination with possible overshoot bounciness)</summary>
  99. *
  100. * @method LeanSmooth.spring (float)
  101. * @param {float} current:float the current value
  102. * @param {float} target:float the value we are trying to reach
  103. * @param {float} currentVelocity:float the current velocity of the value
  104. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  105. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  106. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  107. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  108. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  109. * @example
  110. * followVar = LeanSmooth.spring(followVar, destinationVar, ref followVelocity, 1.1f);\n
  111. * Debug.Log("current:"+followVar);
  112. */
  113. public static float spring(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f)
  114. {
  115. if (deltaTime < 0f)
  116. deltaTime = Time.deltaTime;
  117. float diff = target - current;
  118. currentVelocity += deltaTime / smoothTime * accelRate * diff;
  119. currentVelocity *= (1f - deltaTime * friction);
  120. if (maxSpeed > 0f && maxSpeed < Mathf.Abs(currentVelocity))
  121. currentVelocity = maxSpeed * Mathf.Sign(currentVelocity);
  122. float returned = current + currentVelocity;
  123. return returned;
  124. }
  125. /**
  126. * <summary>Moves one value towards another (eases in and out to destination with possible overshoot bounciness)</summary>
  127. *
  128. * @method LeanSmooth.spring (Vector3)
  129. * @param {Vector3} current:float the current value
  130. * @param {Vector3} target:float the value we are trying to reach
  131. * @param {Vector3} currentVelocity:float the current velocity of the value
  132. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  133. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  134. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  135. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  136. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  137. * @example
  138. * transform.position = LeanSmooth.spring(transform.position, destTrans.position, ref followVelocity, 1.1f);\n
  139. * Debug.Log("current:"+transform.position);
  140. */
  141. public static Vector3 spring(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f)
  142. {
  143. float x = spring(current.x, target.x, ref currentVelocity.x, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  144. float y = spring(current.y, target.y, ref currentVelocity.y, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  145. float z = spring(current.z, target.z, ref currentVelocity.z, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  146. return new Vector3(x, y, z);
  147. }
  148. /**
  149. * <summary>Moves one color towards another (eases in and out to destination with possible overshoot bounciness)</summary>
  150. *
  151. * @method LeanSmooth.spring (Color)
  152. * @param {Color} current:float the current value
  153. * @param {Color} target:float the value we are trying to reach
  154. * @param {Color} currentVelocity:float the current velocity of the value
  155. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  156. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  157. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  158. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  159. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  160. * @example
  161. * fromColor = LeanSmooth.spring(fromColor, transform.GetComponent<Renderer>().material.color, ref velocityColor, 1.1f);\n
  162. * Debug.Log("current:"+fromColor);
  163. */
  164. public static Color spring(Color current, Color target, ref Color currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f)
  165. {
  166. float r = spring(current.r, target.r, ref currentVelocity.r, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  167. float g = spring(current.g, target.g, ref currentVelocity.g, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  168. float b = spring(current.b, target.b, ref currentVelocity.b, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  169. float a = spring(current.a, target.a, ref currentVelocity.a, smoothTime, maxSpeed, deltaTime, friction, accelRate);
  170. return new Color(r, g, b, a);
  171. }
  172. /**
  173. * <summary>Moves one value towards another (at a constant speed)</summary>
  174. *
  175. * @method LeanSmooth.linear (float)
  176. * @param {float} current:float the current value
  177. * @param {float} target:float the value we are trying to reach
  178. * @param {float} moveSpeed:float the speed at which to move towards the target
  179. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  180. * @example
  181. * followVar = LeanSmooth.linear(followVar, destinationVar, 50f);\n
  182. * Debug.Log("current:"+followVar);
  183. */
  184. public static float linear(float current, float target, float moveSpeed, float deltaTime = -1f)
  185. {
  186. if (deltaTime < 0f)
  187. deltaTime = Time.deltaTime;
  188. bool targetGreater = (target > current);
  189. float currentVelocity = deltaTime * moveSpeed * (targetGreater ? 1f : -1f);
  190. float returned = current + currentVelocity;
  191. float returnPassed = returned - target;
  192. if ((targetGreater && returnPassed > 0) || !targetGreater && returnPassed < 0)
  193. { // Has passed point, return target
  194. return target;
  195. }
  196. return returned;
  197. }
  198. /**
  199. * <summary>Moves one value towards another (at a constant speed)</summary>
  200. *
  201. * @method LeanSmooth.linear (Vector3)
  202. * @param {Vector3} current:float the current value
  203. * @param {Vector3} target:float the value we are trying to reach
  204. * @param {float} moveSpeed:float the speed at which to move towards the target
  205. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  206. * @example
  207. * transform.position = LeanSmooth.linear(transform.position, followTrans.position, 50f);\n
  208. * Debug.Log("current:"+transform.position);
  209. */
  210. public static Vector3 linear(Vector3 current, Vector3 target, float moveSpeed, float deltaTime = -1f)
  211. {
  212. float x = linear(current.x, target.x, moveSpeed, deltaTime);
  213. float y = linear(current.y, target.y, moveSpeed, deltaTime);
  214. float z = linear(current.z, target.z, moveSpeed, deltaTime);
  215. return new Vector3(x, y, z);
  216. }
  217. /**
  218. * <summary>Moves one color towards another (at a constant speed)</summary>
  219. *
  220. * @method LeanSmooth.linear (Color)
  221. * @param {Color} current:float the current value
  222. * @param {Color} target:float the value we are trying to reach
  223. * @param {float} moveSpeed:float the speed at which to move towards the target
  224. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  225. * @example
  226. * fromColor = LeanSmooth.linear(fromColor, transform.GetComponent<Renderer>().material.color, 50f);\n
  227. * Debug.Log("current:"+fromColor);
  228. */
  229. public static Color linear(Color current, Color target, float moveSpeed)
  230. {
  231. float r = linear(current.r, target.r, moveSpeed);
  232. float g = linear(current.g, target.g, moveSpeed);
  233. float b = linear(current.b, target.b, moveSpeed);
  234. float a = linear(current.a, target.a, moveSpeed);
  235. return new Color(r, g, b, a);
  236. }
  237. /**
  238. * <summary>Moves one value towards another (with an ease that bounces back some when it reaches it's destination)</summary>
  239. *
  240. * @method LeanSmooth.bounceOut (float)
  241. * @param {float} current:float the current value
  242. * @param {float} target:float the value we are trying to reach
  243. * @param {float} currentVelocity:float the current velocity of the value
  244. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  245. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  246. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  247. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  248. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  249. * @param {float} [hitDamping]:float the rate at which to dampen the bounciness of when it reaches it's destination
  250. * @example
  251. * followVar = LeanSmooth.bounceOut(followVar, destinationVar, ref followVelocity, 1.1f);\n
  252. * Debug.Log("current:"+followVar);
  253. */
  254. public static float bounceOut(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f, float hitDamping = 0.9f)
  255. {
  256. if (deltaTime < 0f)
  257. deltaTime = Time.deltaTime;
  258. float diff = target - current;
  259. currentVelocity += deltaTime / smoothTime * accelRate * diff;
  260. currentVelocity *= (1f - deltaTime * friction);
  261. if (maxSpeed > 0f && maxSpeed < Mathf.Abs(currentVelocity))
  262. currentVelocity = maxSpeed * Mathf.Sign(currentVelocity);
  263. float returned = current + currentVelocity;
  264. bool targetGreater = (target > current);
  265. float returnPassed = returned - target;
  266. if ((targetGreater && returnPassed > 0) || !targetGreater && returnPassed < 0)
  267. { // Start a bounce
  268. currentVelocity = -currentVelocity * hitDamping;
  269. returned = current + currentVelocity;
  270. }
  271. return returned;
  272. }
  273. /**
  274. * <summary>Moves one value towards another (with an ease that bounces back some when it reaches it's destination)</summary>
  275. *
  276. * @method LeanSmooth.bounceOut (Vector3)
  277. * @param {Vector3} current:float the current value
  278. * @param {Vector3} target:float the value we are trying to reach
  279. * @param {Vector3} currentVelocity:float the current velocity of the value
  280. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  281. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  282. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  283. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  284. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  285. * @param {float} [hitDamping]:float the rate at which to dampen the bounciness of when it reaches it's destination
  286. * @example
  287. * transform.position = LeanSmooth.bounceOut(transform.position, followTrans.position, ref followVelocity, 1.1f);\n
  288. * Debug.Log("current:"+transform.position);
  289. */
  290. public static Vector3 bounceOut(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f, float hitDamping = 0.9f)
  291. {
  292. float x = bounceOut(current.x, target.x, ref currentVelocity.x, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  293. float y = bounceOut(current.y, target.y, ref currentVelocity.y, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  294. float z = bounceOut(current.z, target.z, ref currentVelocity.z, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  295. return new Vector3(x, y, z);
  296. }
  297. /**
  298. * <summary>Moves one color towards another (with an ease that bounces back some when it reaches it's destination)</summary>
  299. *
  300. * @method LeanSmooth.bounceOut (Color)
  301. * @param {Color} current:float the current value
  302. * @param {Color} target:float the value we are trying to reach
  303. * @param {Color} currentVelocity:float the current velocity of the value
  304. * @param {float} smoothTime:float roughly the time it takes to reach the destination
  305. * @param {float} maxSpeed:float the top speed you want the value to move at (defaults to unlimited -1f)
  306. * @param {float} deltaTime:float the difference in time since the method was called (defaults to Time.deltaTime)
  307. * @param {float} [friction]:float rate at which the spring is slowed down once it reaches it's destination
  308. * @param {float} [accelRate]:float the rate it accelerates from it's initial position
  309. * @param {float} [hitDamping]:float the rate at which to dampen the bounciness of when it reaches it's destination
  310. * @example
  311. * fromColor = LeanSmooth.bounceOut(fromColor, transform.GetComponent<Renderer>().material.color, ref followVelocity, 1.1f);\n
  312. * Debug.Log("current:" + fromColor);
  313. */
  314. public static Color bounceOut(Color current, Color target, ref Color currentVelocity, float smoothTime, float maxSpeed = -1f, float deltaTime = -1f, float friction = 2f, float accelRate = 0.5f, float hitDamping = 0.9f)
  315. {
  316. float r = bounceOut(current.r, target.r, ref currentVelocity.r, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  317. float g = bounceOut(current.g, target.g, ref currentVelocity.g, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  318. float b = bounceOut(current.b, target.b, ref currentVelocity.b, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  319. float a = bounceOut(current.a, target.a, ref currentVelocity.a, smoothTime, maxSpeed, deltaTime, friction, accelRate, hitDamping);
  320. return new Color(r, g, b, a);
  321. }
  322. }