RigidbodyTimeline2D.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. using UnityEngine;
  2. namespace Chronos
  3. {
  4. public class RigidbodyTimeline2D : RigidbodyTimeline<Rigidbody2D, RigidbodyTimeline2D.Snapshot>
  5. {
  6. // Scale is disabled by default because it usually doesn't change and
  7. // would otherwise take more memory. Feel free to uncomment the lines
  8. // below if you need to record it.
  9. public struct Snapshot
  10. {
  11. public Vector3 position;
  12. public Quaternion rotation;
  13. // public Vector3 scale;
  14. public Vector2 velocity;
  15. public float angularVelocity;
  16. public float drag;
  17. public float angularDrag;
  18. public float lastPositiveTimeScale;
  19. public static Snapshot Lerp(Snapshot from, Snapshot to, float t)
  20. {
  21. return new Snapshot()
  22. {
  23. position = Vector3.Lerp(from.position, to.position, t),
  24. rotation = Quaternion.Lerp(from.rotation, to.rotation, t),
  25. // scale = Vector3.Lerp(from.scale, to.scale, t),
  26. velocity = Vector2.Lerp(from.velocity, to.velocity, t),
  27. angularVelocity = Mathf.Lerp(from.angularVelocity, to.angularVelocity, t),
  28. drag = Mathf.Lerp(from.drag, to.drag, t),
  29. angularDrag = Mathf.Lerp(from.angularDrag, to.angularDrag, t),
  30. lastPositiveTimeScale = Mathf.Lerp(from.lastPositiveTimeScale, to.lastPositiveTimeScale, t),
  31. };
  32. }
  33. }
  34. public RigidbodyTimeline2D(Timeline timeline, Rigidbody2D component) : base(timeline, component) { }
  35. public override void CopyProperties(Rigidbody2D source)
  36. {
  37. bodyType = source.bodyType;
  38. gravityScale = source.gravityScale;
  39. source.gravityScale = 0;
  40. }
  41. public override void FixedUpdate()
  42. {
  43. if (isReallyManual && !isManual) // Chronos-manual, not user-manual
  44. {
  45. // Fix for 2D kinematic rigidbodies keeping their velocity.
  46. realVelocity = Vector3.zero;
  47. realAngularVelocity = Vector3.zero;
  48. }
  49. if (!isReallyManual && timeline.timeScale > 0)
  50. {
  51. velocity += (Physics2D.gravity * gravityScale * timeline.fixedDeltaTime);
  52. }
  53. }
  54. #region Snapshots
  55. protected override Snapshot LerpSnapshots(Snapshot from, Snapshot to, float t)
  56. {
  57. return Snapshot.Lerp(from, to, t);
  58. }
  59. protected override Snapshot CopySnapshot()
  60. {
  61. return new Snapshot()
  62. {
  63. position = component.transform.position,
  64. rotation = component.transform.rotation,
  65. // scale = component.transform.localScale,
  66. velocity = component.velocity,
  67. angularVelocity = component.angularVelocity,
  68. drag = component.drag,
  69. angularDrag = component.angularDrag,
  70. lastPositiveTimeScale = lastPositiveTimeScale
  71. };
  72. }
  73. protected override void ApplySnapshot(Snapshot snapshot)
  74. {
  75. component.transform.position = snapshot.position;
  76. component.transform.rotation = snapshot.rotation;
  77. // component.transform.localScale = snapshot.scale;
  78. if (timeline.timeScale > 0)
  79. {
  80. component.velocity = snapshot.velocity;
  81. component.angularVelocity = snapshot.angularVelocity;
  82. }
  83. component.drag = snapshot.drag;
  84. component.angularDrag = snapshot.angularDrag;
  85. lastPositiveTimeScale = snapshot.lastPositiveTimeScale;
  86. }
  87. #endregion
  88. #region Components
  89. protected float realGravityScale
  90. {
  91. get { return component.gravityScale; }
  92. set { component.gravityScale = value; }
  93. }
  94. protected override bool isReallyManual
  95. {
  96. get { return realBodyType == RigidbodyType2D.Kinematic; }
  97. set { realBodyType = value ? RigidbodyType2D.Kinematic : bodyType; }
  98. }
  99. private RigidbodyType2D realBodyType
  100. {
  101. get { return component.bodyType; }
  102. set { component.bodyType = value; }
  103. }
  104. protected override float realMass
  105. {
  106. get { return component.mass; }
  107. set { component.mass = value; }
  108. }
  109. protected override Vector3 realVelocity
  110. {
  111. get { return component.velocity; }
  112. set { component.velocity = value; }
  113. }
  114. protected override Vector3 realAngularVelocity
  115. {
  116. get { return component.angularVelocity * Vector3.one; }
  117. set { component.angularVelocity = value.x; }
  118. }
  119. protected override float realDrag
  120. {
  121. get { return component.drag; }
  122. set { component.drag = value; }
  123. }
  124. protected override float realAngularDrag
  125. {
  126. get { return component.angularDrag; }
  127. set { component.angularDrag = value; }
  128. }
  129. protected override bool IsSleeping()
  130. {
  131. return component.IsSleeping();
  132. }
  133. protected override void WakeUp()
  134. {
  135. component.WakeUp();
  136. }
  137. private RigidbodyType2D _bodyType;
  138. /// <summary>
  139. /// The body type of the rigidbody before time effects. Use this property instead of Rigidbody2D.bodyType, which will be overwritten by the physics timer at runtime.
  140. /// </summary>
  141. public RigidbodyType2D bodyType
  142. {
  143. get
  144. {
  145. return _bodyType;
  146. }
  147. set
  148. {
  149. _bodyType = value;
  150. // Avoid frame delay if we're adding a force right after
  151. // https://support.ludiq.io/forums/1-chronos/topics/464-/
  152. if (timeline.timeScale > 0)
  153. {
  154. realBodyType = value;
  155. }
  156. }
  157. }
  158. protected override bool isManual
  159. {
  160. get { return bodyType == RigidbodyType2D.Kinematic; }
  161. }
  162. /// <summary>
  163. /// The gravity scale of the rigidbody. Use this property instead of Rigidbody2D.gravityScale, which will be overwritten by the physics timer at runtime.
  164. /// </summary>
  165. public float gravityScale { get; set; }
  166. /// <summary>
  167. /// The velocity of the rigidbody before time effects. Use this property instead of Rigidbody2D.velocity, which will be overwritten by the physics timer at runtime.
  168. /// </summary>
  169. public Vector2 velocity
  170. {
  171. get
  172. {
  173. if (timeline.timeScale == 0)
  174. {
  175. return zeroSnapshot.velocity;
  176. }
  177. return realVelocity / timeline.timeScale;
  178. }
  179. set { if (AssertForwardProperty("velocity", Severity.Ignore)) realVelocity = value * timeline.timeScale; }
  180. }
  181. /// <summary>
  182. /// The angular velocity of the rigidbody before time effects. Use this property instead of Rigidbody2D.angularVelocity, which will be overwritten by the physics timer at runtime.
  183. /// </summary>
  184. public float angularVelocity
  185. {
  186. get
  187. {
  188. if (timeline.timeScale == 0)
  189. {
  190. return zeroSnapshot.angularVelocity;
  191. }
  192. return realAngularVelocity.x / timeline.timeScale;
  193. }
  194. set
  195. {
  196. if (AssertForwardProperty("angularVelocity", Severity.Ignore))
  197. realAngularVelocity = value * Vector3.one * timeline.timeScale;
  198. }
  199. }
  200. /// <summary>
  201. /// The equivalent of Rigidbody2D.AddForce adjusted for time effects.
  202. /// </summary>
  203. public void AddForce(Vector2 force, ForceMode2D mode = ForceMode2D.Force)
  204. {
  205. if (AssertForwardForce(Severity.Ignore))
  206. component.AddForce(AdjustForce(force), mode);
  207. }
  208. /// <summary>
  209. /// The equivalent of Rigidbody2D.AddRelativeForce adjusted for time effects.
  210. /// </summary>
  211. public void AddRelativeForce(Vector2 force, ForceMode2D mode = ForceMode2D.Force)
  212. {
  213. if (AssertForwardForce(Severity.Ignore))
  214. component.AddRelativeForce(AdjustForce(force), mode);
  215. }
  216. /// <summary>
  217. /// The equivalent of Rigidbody2D.AddForceAtPosition adjusted for time effects.
  218. /// </summary>
  219. public void AddForceAtPosition(Vector2 force, Vector2 position, ForceMode2D mode = ForceMode2D.Force)
  220. {
  221. if (AssertForwardForce(Severity.Ignore))
  222. component.AddForceAtPosition(AdjustForce(force), position, mode);
  223. }
  224. /// <summary>
  225. /// The equivalent of Rigidbody2D.AddTorque adjusted for time effects.
  226. /// </summary>
  227. public void AddTorque(float torque, ForceMode2D mode = ForceMode2D.Force)
  228. {
  229. if (AssertForwardForce(Severity.Ignore))
  230. component.AddTorque(AdjustForce(torque), mode);
  231. }
  232. #endregion
  233. }
  234. }