From d4b6fdc153cc42ac3082759c5a59cf417b1e65b9 Mon Sep 17 00:00:00 2001 From: Pete Goodfellow Date: Tue, 26 Jan 2021 15:47:48 +0000 Subject: [PATCH] TimerManager now persists through scene changes, and timers may opt out of destruction on scene change. --- Source/Timer.cs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Source/Timer.cs b/Source/Timer.cs index 6878c0a..db46ced 100644 --- a/Source/Timer.cs +++ b/Source/Timer.cs @@ -6,8 +6,8 @@ */ using UnityEngine; +using UnityEngine.SceneManagement; using System; -using System.Linq; using System.Collections.Generic; using JetBrains.Annotations; using Object = UnityEngine.Object; @@ -91,7 +91,7 @@ public bool isDone /// after the parent has been destroyed. /// A timer object that allows you to examine stats and stop/resume progress. public static Timer Register(float duration, Action onComplete, Action onUpdate = null, - bool isLooped = false, bool useRealTime = false, MonoBehaviour autoDestroyOwner = null) + bool isLooped = false, bool useRealTime = false, MonoBehaviour autoDestroyOwner = null, bool cancelOnSceneChange = true) { // create a manager object to update all the timers if one does not already exist. if (Timer._manager == null) @@ -105,10 +105,11 @@ public static Timer Register(float duration, Action onComplete, Action on { GameObject managerObject = new GameObject { name = "TimerManager" }; Timer._manager = managerObject.AddComponent(); + GameObject.DontDestroyOnLoad(managerObject); } } - Timer timer = new Timer(duration, onComplete, onUpdate, isLooped, useRealTime, autoDestroyOwner); + Timer timer = new Timer(duration, onComplete, onUpdate, isLooped, useRealTime, autoDestroyOwner, cancelOnSceneChange); Timer._manager.RegisterTimer(timer); return timer; } @@ -314,12 +315,14 @@ private bool isOwnerDestroyed private readonly MonoBehaviour _autoDestroyOwner; private readonly bool _hasAutoDestroyOwner; + private readonly bool _cancelOnSceneChange; + #endregion #region Private Constructor (use static Register method to create new timer) private Timer(float duration, Action onComplete, Action onUpdate, - bool isLooped, bool usesRealTime, MonoBehaviour autoDestroyOwner) + bool isLooped, bool usesRealTime, MonoBehaviour autoDestroyOwner, bool cancelOnSceneChange) { this.duration = duration; this._onComplete = onComplete; @@ -331,6 +334,8 @@ private Timer(float duration, Action onComplete, Action onUpdate, this._autoDestroyOwner = autoDestroyOwner; this._hasAutoDestroyOwner = autoDestroyOwner != null; + this._cancelOnSceneChange = cancelOnSceneChange; + this._startTime = this.GetWorldTime(); this._lastUpdateTime = this._startTime; } @@ -410,6 +415,29 @@ private class TimerManager : MonoBehaviour // buffer adding timers so we don't edit a collection during iteration private List _timersToAdd = new List(); + [UsedImplicitly] + public void OnEnable() + { + SceneManager.activeSceneChanged += ActiveSceneChanged; + } + + [UsedImplicitly] + public void OnDisable() + { + SceneManager.activeSceneChanged -= ActiveSceneChanged; + } + + private void ActiveSceneChanged(Scene from, Scene to) + { + foreach (Timer timer in this._timers) + { + if(timer._cancelOnSceneChange) + { + timer.Cancel(); + } + } + } + public void RegisterTimer(Timer timer) { this._timersToAdd.Add(timer);