Run actions after a delay in Unity3D.
This library has been battle-tested and hardened throughout numerous projects, including the award-winning Pitfall Planet.
Written by Alexander Biggs + Adam Robinson-Yu.
Fork by GH-ZJ([email protected])
The Unity Timer package provides the following method for creating timers:
public static DelayTimer DelayAction(float duration, Action onComplete, Action<float> onUpdate = null, bool useRealTime = false, Object autoDestroyOwner = null);
public static DelayFrameTimer DelayFrameAction(int frame, Action onComplete, Action<float> onUpdate = null, Object autoDestroyOwner = null);
public static LoopTimer LoopAction(float interval, Action<int> onComplete, Action<float> onUpdate = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
public static LoopUntilTimer LoopUntilAction(float interval, Func<LoopUntilTimer, bool> loopUntil, Action<int> onComplete, Action<float> onUpdate = null, Action onFinished = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
public static LoopCountTimer LoopCountAction(float interval, int loopCount, Action<int> onComplete, Action<float> onUpdate = null, Action onFinished = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
public static DelayTimer PersistenceDelayAction(float duration, Action onComplete, Action<float> onUpdate = null, bool useRealTime = false, Object autoDestroyOwner = null);
public static DelayFrameTimer PersistenceDelayFrameAction(int frame, Action onComplete, Action<float> onUpdate = null, Object autoDestroyOwner = null);
public static LoopTimer PersistenceLoopAction(float interval, Action<int> onComplete, Action<float> onUpdate = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
public static LoopUntilTimer PersistenceLoopUntilAction(float interval, Func<LoopUntilTimer, bool> loopUntil, Action<int> onComplete, Action<float> onUpdate = null, Action onFinished = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
public static LoopCountTimer PersistenceLoopCountAction(float interval, int loopCount, Action<int> onComplete, Action<float> onUpdate = null, Action onFinished = null, bool useRealTime = false, bool executeOnStart = false, Object autoDestroyOwner = null);
Out of the box, without this library, there are two main ways of handling timers in Unity:
startTime = Time.time
), then check in an Update call if Time.time - startTime >= timerDuration
.The first method is verbose, forcing you to refactor your code to use IEnumerator functions. Furthermore, it necessitates having access to a MonoBehaviour instance to start the coroutine, meaning that solution will not work in non-MonoBehaviour classes. Finally, there is no way to prevent WaitForSeconds from being affected by changes to the time scale.
The second method is error-prone, and hides away the actual game logic that you are trying to express.
This library alleviates both of these concerns, making it easy to add an easy-to-read, expressive timer to any class in your Unity project.
private void Start()
{
Timer.LoopAction(5, loopTime => { Debug.LogError("Timer Called: " + loopTime); });
}
executeOnStart
to true.private void Start()
{
Timer.LoopAction(5, loopTime => { Debug.LogError("Timer Called: " + loopTime); }, executeOnStart: true);
}
private void Start()
{
Timer.DelayFrameAction(5, () => { Debug.LogError("Timer Called"); });
}
useRealTime
to true.private void Start()
{
Timer.DelayAction(5, () => { Debug.LogError("Timer Called"); }, useRealTime: true);
}
updateMode
to Timer.UpdateMode.GameTime
or Timer.UpdateMode.UnscaledGameTime
or Timer.UpdateMode.RealTime
.Timer.UpdateMode.GameTime
.private void Start()
{
Timer.DelayAction(5, () => { Debug.LogError("Timer Called"); }, null, Timer.UpdateMode.UnscaledGameTime);
}
Timer timer;
void Start() {
timer = Timer.LoopAction(5, _ => { Debug.LogError("Timer Called"); });
}
void Update() {
if (Input.GetKeyDown(KeyCode.X)) {
Timer.Cancel(timer);
}
}
autoDestroyOwner
to the UnityEngine.Object, so that the timer is destroyed when the UnityEngine.Object is.Very often, a timer called from a Component will manipulate that component's state. Thus, it is common practice to cancel the timer in the OnDestroy method of the Component. We've added a convenient extension method that attaches a Timer to a Component such that it will automatically cancel the timer when the Component is detected as null.
public class CoolMonoBehaviour : MonoBehaviour {
private void Start()
{
//The timer will cancel when the Component is destroyed;
Timer.DelayAction(5, () => { Debug.LogError("Timer Called"); }, useRealTime: true, autoDestroyOwner: this);
}
private void Update()
{
// This code could destroy the object at any time!
if (Input.GetKeyDown(KeyCode.X)) {
GameObject.Destroy(this.gameObject);
}
}
}
onUpdate
callback.// Change a color from white to red over the course of five seconds.
Color color = Color.white;
float transitionDuration = 5f;
Timer.DelayAction(transitionDuration,
onUpdate: secondsElapsed => color.r = 255 * (secondsElapsed / transitionDuration),
onComplete: () => Debug.Log("Color is now red"));
timer.Pause()
timer.Resume()
timer.Cancel()
timer.Restart()
timer.GetTimeElapsed()
timer.GetTimeRemaining()
timer.GetRatioComplete()
timer.isDone
Timer.CancelAllRegisteredTimers()
Timer.CancelAllRegisteredTimersByOwner(owner)
Timer.PauseAllRegisteredTimers()
Timer.ResumeAllRegisteredTimers()
Timer.XXXAllRegisteredTimers()
function by call Timer.PersistenceXXX()
function.Timer timer;
void Start() {
//The timer will not cancel when Timer.XXXAllRegisteredTimers();
timer = Timer.PersistenceLoopAction(5, _ => { Debug.LogError("Timer Called"); });
}
void Update() {
//No effect to timer
if (Input.GetKeyDown(KeyCode.X))
Timer.CancelAllRegisteredTimers();
//Only this can cancel persistence timer
if(Input.GetKeyDown(KeyCode.C))
Timer.Cancel(timer);//same to timer?.Cancel();
}
void Start() {
//The timer will attach to the Component instance.
this.DelayAction(5, () => { Debug.LogError("Timer Called"); });
}
/Example
folder.DontDestroyOnLoad
.