RigidbodyTimeline.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using UnityEngine;
  2. namespace Chronos
  3. {
  4. public interface IRigidbodyTimeline
  5. {
  6. float mass { get; set; }
  7. float drag { get; set; }
  8. float angularDrag { get; set; }
  9. }
  10. public abstract class RigidbodyTimeline<TComponent, TSnapshot> : RecorderTimeline<TComponent, TSnapshot>, IRigidbodyTimeline where TComponent : Component
  11. {
  12. public RigidbodyTimeline(Timeline timeline, TComponent component) : base(timeline, component) { }
  13. public override void Update()
  14. {
  15. float timeScale = timeline.timeScale;
  16. if (lastTimeScale != 0 && timeScale == 0) // Arrived at halt
  17. {
  18. if (lastTimeScale > 0)
  19. {
  20. zeroSnapshot = CopySnapshot();
  21. var nav = component.GetComponent<UnityEngine.AI.NavMeshAgent>();
  22. if (nav != null)
  23. {
  24. zeroDestination = nav.destination;
  25. }
  26. }
  27. else if (lastTimeScale < 0 && timeline.rewindable)
  28. {
  29. zeroSnapshot = interpolatedSnapshot;
  30. }
  31. zeroTime = timeline.time;
  32. }
  33. if (lastTimeScale >= 0 && timeScale <= 0) // Started pause or rewind
  34. {
  35. if (timeScale < 0) // Started rewind
  36. {
  37. laterSnapshot = CopySnapshot();
  38. laterTime = timeline.time;
  39. interpolatedSnapshot = laterSnapshot;
  40. canRewind = TryFindEarlierSnapshot(false);
  41. }
  42. isReallyManual = true;
  43. }
  44. else if (lastTimeScale <= 0 && timeScale > 0) // Stopped pause or rewind
  45. {
  46. isReallyManual = isManual;
  47. if (lastTimeScale == 0) // Stopped pause
  48. {
  49. ApplySnapshot(zeroSnapshot);
  50. //var nav = component.GetComponent<UnityEngine.AI.NavMeshAgent>();
  51. //if (nav != null && nav.enabled)
  52. //{
  53. // nav.destination = zeroDestination;
  54. //}
  55. }
  56. else if (lastTimeScale < 0 && timeline.rewindable) // Stopped rewind
  57. {
  58. ApplySnapshot(interpolatedSnapshot);
  59. }
  60. WakeUp();
  61. Record();
  62. }
  63. if (timeScale > 0 && timeScale != lastTimeScale && !isReallyManual) // Slowed down or accelerated
  64. {
  65. float modifier = timeScale / lastPositiveTimeScale;
  66. realVelocity *= modifier;
  67. realAngularVelocity *= modifier;
  68. realDrag *= modifier;
  69. realAngularDrag *= modifier;
  70. WakeUp();
  71. }
  72. if (timeScale > 0)
  73. {
  74. isReallyManual = isManual;
  75. Progress();
  76. }
  77. else if (timeScale < 0)
  78. {
  79. Rewind();
  80. }
  81. lastTimeScale = timeScale;
  82. if (timeScale > 0)
  83. {
  84. lastPositiveTimeScale = timeScale;
  85. }
  86. }
  87. #region Fields
  88. protected float lastPositiveTimeScale = 1;
  89. protected TSnapshot zeroSnapshot;
  90. protected float zeroTime;
  91. protected Vector3 zeroDestination;
  92. #endregion
  93. #region Snapshots
  94. public override void Reset()
  95. {
  96. lastPositiveTimeScale = 1;
  97. base.Reset();
  98. }
  99. public override void ModifySnapshots(SnapshotModifier modifier)
  100. {
  101. base.ModifySnapshots(modifier);
  102. zeroSnapshot = modifier(zeroSnapshot, zeroTime);
  103. }
  104. #endregion
  105. #region Rigidbody
  106. protected abstract bool isReallyManual { get; set; }
  107. protected abstract float realMass { get; set; }
  108. protected abstract Vector3 realVelocity { get; set; }
  109. protected abstract Vector3 realAngularVelocity { get; set; }
  110. protected abstract float realDrag { get; set; }
  111. protected abstract float realAngularDrag { get; set; }
  112. protected abstract bool IsSleeping();
  113. protected abstract void WakeUp();
  114. protected abstract bool isManual { get; }
  115. /// <summary>
  116. /// The mass of the rigidbody before time effects. Use this property instead of Rigidbody.mass, which will be overwritten by the physics timer at runtime.
  117. /// </summary>
  118. public float mass
  119. {
  120. // This isn't getting used right now, but leave it here for forward-compatibility
  121. get { return realMass; }
  122. set { realMass = value; }
  123. }
  124. /// <summary>
  125. /// The drag of the rigidbody before time effects. Use this property instead of Rigidbody.drag, which will be overwritten by the physics timer at runtime.
  126. /// </summary>
  127. public float drag
  128. {
  129. get { return realDrag / timeline.timeScale; }
  130. set { if (AssertForwardProperty("drag", Severity.Warn)) realDrag = value * timeline.timeScale; }
  131. }
  132. /// <summary>
  133. /// The angular drag of the rigidbody before time effects. Use this property instead of Rigidbody.angularDrag, which will be overwritten by the physics timer at runtime.
  134. /// </summary>
  135. public float angularDrag
  136. {
  137. get { return realAngularDrag / timeline.timeScale; }
  138. set { if (AssertForwardProperty("angularDrag", Severity.Warn)) realAngularDrag = value * timeline.timeScale; }
  139. }
  140. protected virtual float AdjustForce(float force)
  141. {
  142. return force * timeline.timeScale;
  143. }
  144. protected virtual Vector2 AdjustForce(Vector2 force)
  145. {
  146. return force * timeline.timeScale;
  147. }
  148. protected virtual Vector3 AdjustForce(Vector3 force)
  149. {
  150. return force * timeline.timeScale;
  151. }
  152. protected bool AssertForwardProperty(string property, Severity severity)
  153. {
  154. if (timeline.timeScale <= 0)
  155. {
  156. if (severity == Severity.Error)
  157. {
  158. throw new ChronosException("Cannot change the " + property + " of the rigidbody while time is paused or rewinding.");
  159. }
  160. else if (severity == Severity.Warn)
  161. {
  162. Debug.LogWarning("Trying to change the " + property + " of the rigidbody while time is paused or rewinding, ignoring.");
  163. }
  164. }
  165. return timeline.timeScale > 0;
  166. }
  167. protected bool AssertForwardForce(Severity severity)
  168. {
  169. if (timeline.timeScale <= 0)
  170. {
  171. if (severity == Severity.Error)
  172. {
  173. throw new ChronosException("Cannot apply a force to the rigidbody while time is paused or rewinding.");
  174. }
  175. else if (severity == Severity.Warn)
  176. {
  177. Debug.LogWarning("Trying to apply a force to the rigidbody while time is paused or rewinding, ignoring.");
  178. }
  179. }
  180. return timeline.timeScale > 0;
  181. }
  182. #endregion
  183. }
  184. }