Timekeeper.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Chronos
  5. {
  6. /// <summary>
  7. /// A global singleton tasked with keeping track of global clocks in the scene. One and only one Timekeeper is required per scene.
  8. /// </summary>
  9. [DisallowMultipleComponent]
  10. [HelpURL("http://ludiq.io/chronos/documentation#Timekeeper")]
  11. public class Timekeeper : Singleton<Timekeeper>
  12. {
  13. public const int DefaultMaxParticleLoops = 10;
  14. public Timekeeper()
  15. : base(false, false)
  16. {
  17. _clocks = new Dictionary<string, GlobalClock>();
  18. }
  19. protected virtual void Awake()
  20. {
  21. foreach (GlobalClock globalClock in GetComponents<GlobalClock>())
  22. {
  23. _clocks.Add(globalClock.key, globalClock);
  24. }
  25. }
  26. #region Properties
  27. [SerializeField]
  28. private bool _debug = false;
  29. /// <summary>
  30. /// Determines whether Chronos should display debug messages and gizmos in the editor.
  31. /// </summary>
  32. public bool debug
  33. {
  34. get { return _debug; }
  35. set { _debug = value; }
  36. }
  37. [SerializeField]
  38. private int _maxParticleLoops = DefaultMaxParticleLoops;
  39. /// <summary>
  40. /// The maximum loops during which particle systems should be allowed to run before resetting.
  41. /// </summary>
  42. public int maxParticleLoops
  43. {
  44. get { return _maxParticleLoops; }
  45. set { _maxParticleLoops = value; }
  46. }
  47. #endregion
  48. #region Clocks
  49. protected Dictionary<string, GlobalClock> _clocks;
  50. /// <summary>
  51. /// An enumeration of all the global clocks on the timekeeper.
  52. /// </summary>
  53. public IEnumerable<GlobalClock> clocks
  54. {
  55. get { return _clocks.Values; }
  56. }
  57. /// <summary>
  58. /// Determines whether the timekeeper has a global clock with the specified key.
  59. /// </summary>
  60. public virtual bool HasClock(string key)
  61. {
  62. if (key == null) throw new ArgumentNullException("key");
  63. return _clocks.ContainsKey(key);
  64. }
  65. /// <summary>
  66. /// Returns the global clock with the specified key.
  67. /// </summary>
  68. public virtual GlobalClock Clock(string key)
  69. {
  70. if (key == null) throw new ArgumentNullException("key");
  71. if (!HasClock(key))
  72. {
  73. throw new ChronosException(string.Format("Unknown global clock '{0}'.", key));
  74. }
  75. return _clocks[key];
  76. }
  77. /// <summary>
  78. /// Adds a global clock with the specified key and returns it.
  79. /// </summary>
  80. public virtual GlobalClock AddClock(string key)
  81. {
  82. if (key == null) throw new ArgumentNullException("key");
  83. if (HasClock(key))
  84. {
  85. throw new ChronosException(string.Format("Global clock '{0}' already exists.", key));
  86. }
  87. GlobalClock clock = gameObject.AddComponent<GlobalClock>();
  88. clock.key = key;
  89. _clocks.Add(key, clock);
  90. return clock;
  91. }
  92. /// <summary>
  93. /// Removes the global clock with the specified key.
  94. /// </summary>
  95. public virtual void RemoveClock(string key)
  96. {
  97. if (key == null) throw new ArgumentNullException("key");
  98. if (!HasClock(key))
  99. {
  100. throw new ChronosException(string.Format("Unknown global clock '{0}'.", key));
  101. }
  102. _clocks.Remove(key);
  103. }
  104. #endregion
  105. internal static TimeState GetTimeState(float timeScale)
  106. {
  107. if (timeScale < 0)
  108. {
  109. return TimeState.Reversed;
  110. }
  111. else if (timeScale == 0)
  112. {
  113. return TimeState.Paused;
  114. }
  115. else if (timeScale < 1)
  116. {
  117. return TimeState.Slowed;
  118. }
  119. else if (timeScale == 1)
  120. {
  121. return TimeState.Normal;
  122. }
  123. else // if (timeScale > 1)
  124. {
  125. return TimeState.Accelerated;
  126. }
  127. }
  128. // Unscaled delta time does not automatically behave like delta time.
  129. // Hacky workaround for now, fixing 2 / 3 issues
  130. // See: http://forum.unity3d.com/threads/138432/#post-2251561
  131. internal static float unscaledDeltaTime
  132. {
  133. get
  134. {
  135. if (Time.frameCount <= 2)
  136. {
  137. return 0.02f;
  138. }
  139. else
  140. {
  141. return Mathf.Min(Time.unscaledDeltaTime, Time.maximumDeltaTime);
  142. }
  143. }
  144. }
  145. }
  146. }