daily pastebin goal
48%
SHARE
TWEET

Timer.cs

mvaganov Oct 24th, 2017 (edited) 176 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. // NonStandard assets
  6. namespace NS {
  7.     public class Timer : MonoBehaviour {
  8.         [System.Serializable]
  9.         public class ToDo {
  10.             public long when;
  11.             public System.Action what;
  12.             public string description;
  13.             public ToDo(long when, System.Action what, string description = null) {
  14.                 this.when = when; this.what = what;
  15.                 this.description = description != null ? description : what.Method.Name;
  16.             }
  17.         }
  18.         /// <summary>using a List, which is contiguous memory, because it's faster than a liked list MOST of time, because of cache misses, and reasonable data loads</summary>
  19.         public List<ToDo> queue = new List<ToDo>();
  20.         /// <summary>The singleton</summary>
  21.         private static Timer s_instance = null;
  22.         public static Timer Instance() {
  23.             if (s_instance == null) {
  24.                 if((s_instance = FindObjectOfType(typeof(Timer)) as Timer) == null) { // find the instance
  25.                     GameObject g = new GameObject("<" + s_instance.GetType().Name + ">");
  26.                     s_instance = g.AddComponent<Timer>(); // if there is no instance, create one
  27.                 }
  28.             }
  29.             return s_instance;
  30.         }
  31.         /// <summary>While this is zero, use system time. As soon as time becomes perturbed, by pause or time scale, keep track of game-time. To reset time back to realtime, use SynchToRealtime()</summary>
  32.         private long timer = 0;
  33.         /// <summary>The timer counts in milliseconds, Unity measures in fractions of a second. This value reconciles fractional milliseconds.</summary>
  34.         private float leftOverTime = 0;
  35.  
  36.         public static long NowRealtime() { return System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; }
  37.  
  38.         public long Now() { return timer == 0 ? NowRealtime() : timer; }
  39.  
  40.         public static long now() { return Instance ().Now (); }
  41.  
  42.         public void SynchToRealtime() { timer = 0; }
  43.  
  44.         private int BestIndexFor(long soon){
  45.             int index = 0;
  46.             for (index = 0; index < queue.Count; ++index) {
  47.                 if (queue [index].when > soon) break;
  48.             }
  49.             return index;
  50.         }
  51.  
  52.         public void SetTimeout(System.Action action, long delayMilliseconds) {
  53.             long soon = Now () + delayMilliseconds;
  54.             queue.Insert(BestIndexFor (soon), new ToDo(soon, action));
  55.         }
  56.  
  57.         public static void setTimeout(System.Action action, long delayMilliseconds) {
  58.             Instance ().SetTimeout (action, delayMilliseconds);
  59.         }
  60.  
  61.         void OnApplicationPause(bool paused) { if (timer == 0) { timer = Now (); } }
  62.        
  63.         void Start () {
  64.             #if UNITY_EDITOR
  65.             // This method is run whenever the playmode state is changed.
  66.             UnityEditor.EditorApplication.pauseStateChanged += (UnityEditor.PauseState ps) => {
  67.                 if (ps == UnityEditor.PauseState.Paused && timer == 0) { timer = Now(); }
  68.             };
  69.             #endif
  70.             if (s_instance != null) { throw new System.Exception ("there should only be one timer!"); }
  71.             s_instance = this;
  72.             timer = 0;
  73.         }
  74.  
  75.         void Update () {
  76.             long now;
  77.             if (timer == 0) {
  78.                 now = Now ();
  79.                 if (Time.timeScale != 1) { timer = now; }
  80.             } else {
  81.                 float deltaTimeMs = (Time.deltaTime * 1000);
  82.                 long deltaTimeMsLong = (long)(deltaTimeMs + leftOverTime);
  83.                 timer += deltaTimeMsLong;
  84.                 leftOverTime = deltaTimeMs - deltaTimeMsLong;
  85.                 now = timer;
  86.             }
  87.             while (queue.Count > 0 && queue [0].when <= now) {
  88.                 ToDo todo = queue [0];
  89.                 queue.RemoveAt (0);
  90.                 todo.what.Invoke ();
  91.             }
  92.         }
  93.     }
  94. }
RAW Paste Data
Top