UnityTimer
Powerful and convenient library for running actions after a delay in Unity3D. Fork from akbiggs/UnityTimer. Add some useful functions.
Install / Use
/learn @Mr-sB/UnityTimerREADME
Unity Timer
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(wustzhangjie@gmail.com)
Basic Example
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);
Motivation
Out of the box, without this library, there are two main ways of handling timers in Unity:
- Use a coroutine with the WaitForSeconds method.
- Store the time that your timer started in a private variable (e.g.
startTime = Time.time), then check in an Update call ifTime.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.
Features
- Make a timer repeat by call Timer.LoopAction.
private void Start()
{
Timer.LoopAction(5, loopTime => { Debug.LogError("Timer Called: " + loopTime); });
}
- Make a loop timer execute when start by setting
executeOnStartto true.
private void Start()
{
Timer.LoopAction(5, loopTime => { Debug.LogError("Timer Called: " + loopTime); }, executeOnStart: true);
}
- Make a timer based on frame count by call Timer.DelayFrameAction.
private void Start()
{
Timer.DelayFrameAction(5, () => { Debug.LogError("Timer Called"); });
}
- Measure time by realtimeSinceStartup
instead of scaled game time by setting [Obsolete("Use updateMode to instead.")]
useRealTimeto true. Default is false.
private void Start()
{
Timer.DelayAction(5, () => { Debug.LogError("Timer Called"); }, useRealTime: true);
}
- Measure time by time or unscaledTime or realtimeSinceStartup
by setting
updateModetoTimer.UpdateMode.GameTimeorTimer.UpdateMode.UnscaledGameTimeorTimer.UpdateMode.RealTime. Default isTimer.UpdateMode.GameTime.
private void Start()
{
Timer.DelayAction(5, () => { Debug.LogError("Timer Called"); }, null, Timer.UpdateMode.UnscaledGameTime);
}
- Cancel a timer after calling it.
Timer timer;
void Start() {
timer = Timer.LoopAction(5, _ => { Debug.LogError("Timer Called"); });
}
void Update() {
if (Input.GetKeyDown(KeyCode.X)) {
Timer.Cancel(timer);
}
}
- Attach the timer to a UnityEngine.Object by setting
autoDestroyOwnerto 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);
}
}
}
- Update a value gradually over time using the
onUpdatecallback.
// 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"));
- A number of other useful features are included!
timer.Pause()timer.Resume()timer.Cancel()timer.Restart()timer.GetTimeElapsed()timer.GetTimeRemaining()timer.GetRatioComplete()timer.isDoneTimer.CancelAllRegisteredTimers()Timer.CancelAllRegisteredTimersByOwner(owner)Timer.PauseAllRegisteredTimers()Timer.ResumeAllRegisteredTimers()
- Make a timer not effect by
Timer.XXXAllRegisteredTimers()function by callTimer.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();
}
- All timer generator functions can shortcut call by using Component/GameObject Extensions functions, and the timer will attach to the Component/GameObject so that the timer is destroyed when the Component/GameObject is.
void Start() {
//The timer will attach to the Component instance.
this.DelayAction(5, () => { Debug.LogError("Timer Called"); });
}
- A test scene + script demoing all the features is included with the package in the
/Examplefolder.
Usage Notes / Caveats
- All timers will not destroy when change scene, because TimerManager is
DontDestroyOnLoad.
Related Skills
node-connect
336.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
336.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
82.8kCommit, push, and open a PR
