Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System;
- /// <summary>
- ///
- /// Delay actions. Keeps all actions in a sorted list to minimize overhead.
- ///
- /// </summary>
- /// <usage>
- ///
- /// DelayedAction.time.Delay( 0.2f, MyAction );
- /// DelayedAction.unscaledTime.Delay( 0.3f, () => Debug.Log("Hello!") );
- ///
- /// DelayedAction.time.At( 13.37f, WinGame );
- /// </usage>
- public class DelayedAction : MonoBehaviour
- {
- static GameObject CreateGhost (string name)
- {
- var go = new GameObject (name);
- GameObject.DontDestroyOnLoad (go);
- go.hideFlags = HideFlags.HideAndDontSave;
- return go;
- }
- static DelayedActionTime _time;
- public static DelayedActionTime time {
- get {
- if (_time == null)
- _time = CreateGhost ("DelayedAction").AddComponent<DelayedActionTime> ();
- return _time;
- }
- }
- static DelayedActionUnscaledTime _unscaledTime;
- public static DelayedActionUnscaledTime unscaledTime {
- get {
- if (_unscaledTime == null)
- _unscaledTime = CreateGhost ("DelayedActionUnscaledTime").AddComponent<DelayedActionUnscaledTime> ();
- return _unscaledTime;
- }
- }
- static DelayedActionRealtimeSinceStartup _realtimeSinceStartup;
- public static DelayedActionRealtimeSinceStartup realtimeSinceStartup {
- get {
- if (_realtimeSinceStartup == null)
- _realtimeSinceStartup = CreateGhost ("DelayedActionRealtimeSinceStartup").AddComponent<DelayedActionRealtimeSinceStartup> ();
- return _realtimeSinceStartup;
- }
- }
- /// <summary>
- /// Creates the using custom time. You are responsible for this object! it does not go away by itself
- /// </summary>
- /// <returns>The using custom time.</returns>
- /// <param name="timeProvider">Time provider.</param>
- public static DelayedActionCustomTime CreateUsingCustomTime (Func <float> timeProvider)
- {
- var component = CreateGhost ("DelayedActionCustomTime").AddComponent<DelayedActionCustomTime> ();
- component.timeProvider = timeProvider;
- return component;
- }
- }
- public struct TimedAction
- {
- public Action action;
- public float time;
- public int id;
- public TimedAction (float time, Action action, int id)
- {
- this.time = time;
- this.action = action;
- this.id = id;
- }
- }
- public class DelayedActionRealtimeSinceStartup : DelayedActionBase
- {
- public float now{ get { return Time.realtimeSinceStartup; } }
- void Update ()
- {
- while (sortedActions.Count > 0 && sortedActions [0].time < Time.realtimeSinceStartup) {
- var a = sortedActions [0];
- sortedActions.RemoveAt (0);
- a.action.Invoke ();
- }
- }
- public int Delay (float delay, Action action)
- {
- return At (Time.realtimeSinceStartup + delay, action);
- }
- public override int At (float time, Action action)
- {
- if (time <= Time.realtimeSinceStartup) { //Execute directly
- action.Invoke ();
- uniqueId++; //Had to return a valid id even if not added to sortedActions
- return uniqueId - 1;
- }
- return base.At (time, action);
- }
- }
- public class DelayedActionTime : DelayedActionBase
- {
- public float now{ get { return Time.time; } }
- void Update ()
- {
- while (sortedActions.Count > 0 && sortedActions [0].time < Time.time) {
- var a = sortedActions [0];
- sortedActions.RemoveAt (0);
- a.action.Invoke ();
- }
- }
- public int Delay (float delay, Action action)
- {
- return At (Time.time + delay, action);
- }
- public override int At (float time, Action action)
- {
- if (time <= Time.time) { //Execute directly
- action.Invoke ();
- uniqueId++; //Had to return a valid id even if not added to sortedActions
- return uniqueId - 1;
- }
- return base.At (time, action);
- }
- }
- public class DelayedActionUnscaledTime : DelayedActionBase
- {
- public float now{ get { return Time.unscaledTime; } }
- void Update ()
- {
- while (sortedActions.Count > 0 && sortedActions [0].time < Time.unscaledTime) {
- var a = sortedActions [0];
- sortedActions.RemoveAt (0);
- a.action.Invoke ();
- }
- }
- public int Delay (float delay, Action action)
- {
- return At (Time.unscaledTime + delay, action);
- }
- public override int At (float time, Action action)
- {
- if (time <= Time.unscaledTime) { //Execute directly
- action.Invoke ();
- uniqueId++; //Had to return a valid id even if not added to sortedActions
- return uniqueId - 1;
- }
- return base.At (time, action);
- }
- }
- public class DelayedActionBase : MonoBehaviour
- {
- internal int uniqueId = int.MinValue;
- internal List<TimedAction> sortedActions = new List<TimedAction> (32);
- internal float lastTime { get; private set; }
- public virtual int At (float time, Action action)
- {
- if (time < lastTime) { //Optimization, lastTime can be removed
- for (int i = 0; i < sortedActions.Count; ++i) {
- if (sortedActions [i].time > time) {
- sortedActions.Insert (i, new TimedAction (time, action, uniqueId++));
- return uniqueId - 1;
- }
- }
- }
- lastTime = time;
- sortedActions.Add (new TimedAction (time, action, uniqueId++));
- return uniqueId - 1;
- }
- public void Remove (int? id)
- {
- if (id.HasValue) {
- Remove (id.Value);
- }
- }
- public void Remove (int id)
- {
- for (int i = 0; i < sortedActions.Count; ++i) {
- if (sortedActions [i].id == id) {
- sortedActions.RemoveAt (i);
- return;
- }
- }
- }
- }
- public class DelayedActionCustomTime : DelayedActionBase
- {
- static float stub ()
- {
- return 0;
- }
- public Func<float> timeProvider = stub;
- //Set this to something useful at runtime.
- public float now{ get { return timeProvider (); } }
- void Update ()
- {
- while (sortedActions.Count > 0 && sortedActions [0].time < timeProvider ()) {
- var a = sortedActions [0];
- sortedActions.RemoveAt (0);
- a.action.Invoke ();
- }
- }
- public int Delay (float delay, Action action)
- {
- return At (timeProvider () + delay, action);
- }
- public override int At (float time, Action action)
- {
- if (time <= timeProvider ()) { //Execute directly
- action.Invoke ();
- uniqueId++; //Had to return a valid id even if not added to sortedActions
- return uniqueId - 1;
- }
- return base.At (time, action);
- }
- }
- public class DelayedTest : MonoBehaviour
- {
- void Start ()
- {
- float now = Time.time;
- var t = DelayedAction.time;
- t.At (10f, () => LogTime ("G 10"));
- t.At (1f, () => LogTime ("C 1"));
- t.At (3f, () => LogTime ("F 3"));
- t.At (2f, () => LogTime ("E 2"));
- t.At (1.5f, () => LogTime ("D at time 115"));
- t.At (0.1f, () => LogTime ("B 0.1"));
- int id = t.Delay (0.0f, () => LogTime ("A unremovable 0"));
- t.Remove (id);
- id = t.Delay (0.0000001f, () => LogTime ("A removable 0.0000001"));
- t.Remove (id);
- t.At ((int)Time.time + 1, SpawnDelay);
- var u = DelayedAction.unscaledTime;
- // u.At (1, () => Time.timeScale = 0f);
- // u.At (1, () => LogTime ("--------- Timescale at " + Time.timeScale));
- // u.At (2, () => LogTime ("Unscaled 2"));
- // u.At (5, () => Time.timeScale = 2f);
- // u.At (5, () => LogTime ("--------- Timescale at " + Time.timeScale));
- // u.At (6, () => LogTime ("Unscaled 6"));
- var r = DelayedAction.realtimeSinceStartup;
- r.At (2, () => LogTime ("Realtime At 2"));
- r.At (r.now + 1, () => LogTime ("Realtime At >now< + 1"));
- var c = DelayedAction.CreateUsingCustomTime (GetMusicTime);
- c.Delay (1, () => LogTime ("Custom time 1"));
- t.Delay (0.1f, () => Heavy (3));
- }
- void Heavy (int left)
- {
- var t = DelayedAction.time;
- if (left <= 0) {
- t.At (t.lastTime, Done);
- return;
- }
- LogTime ("Heavy add random delays " + countMax);
- for (int i = 0; i < countMax; ++i) {
- t.Delay (UnityEngine.Random.value * 5, Add);
- }
- t.Delay (2.5f, () => Heavy (left - 1));
- }
- void Done ()
- {
- LogTime ("Added " + count + "/" + countMax);
- }
- void Add ()
- {
- count++;
- }
- int countMax = 1000;
- int count = 0;
- float GetMusicTime ()
- {
- return 0;
- }
- void LogTime (string message = null)
- {
- Debug.LogFormat ("{3} | time {0:0.00} unscaled {1:0.00} realtime {2:0.00}", Time.time, Time.unscaledTime, Time.realtimeSinceStartup, message);
- }
- bool on;
- void SpawnDelay ()
- {
- Debug.Log ("SpawnDelay " + Time.time);
- on = !on;
- if (on) {
- DelayedAction.time.At ((int)Time.time + 1, SpawnDelay);
- } else {
- DelayedAction.time.Delay (1, SpawnDelay);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement