Why no Timer class?

With every game I create, I find myself having to create my own timer classes… It isn’t extremely difficult to do, but I find that:

  1. The most efficient way to do it is to subtract Time.deltaTime from the current time on the timer in the Update() function. I have tested this method, and it is definitely NOT accurate.
  2. It’s a very redundant process…

I was thinking that maybe they could make a Timer component that we could attach to a GameMaster object, or something like that.

I was just wondering why Unity hasn’t implemented its own Timer classes… I realize that there are a bunch of different timers, but I think if the .NET Framework can do it, so can Unity.

public float delay = 1;
public float time;

void Update() {
        if(time > 0) {
            time -= Time.deltaTime;

            if(time < 0) time = 0;
        }

        if(time == 0){
            //Do stuff here
            time = delay;
        }
}

I Agree
Super simple to do but having to constantly include our own timers that should have the exact same function in every game takes up a lot of typing time. You COULD simply make your own Timer class but then you have to import it yourself into each and every project. If you are like me, you end up forgetting to import some of even the more basic assets.

It’d be nice if there was a way to force Unity to either import certain assets by default or add a dll to some folder in the Unity installation folder that would be automatically used.

You can put asset packages here so that you can see them in the Import Packages list.
C:\Program Files\Unity 4\Editor\Standard Packages

I wonder if this folder lets you automatically import your own dll’s when creating a new project.
C:\Program Files\Unity 4\Editor\Data\Managed

Agreed. At the very least, I would like a more streamlined approach to putting my own assets directly into the editor. It would be a breeze to just click GameObject > Timer, and have an empty GameObject appear with a Timer script attached, OR to just be able to click GameObject > Create Empty, and then Component > Timer. Whichever way they chose to do it, it would be great.

I understand that I could just create a custom Timer component, but when I go to work on another game and open up a new project, it won’t be there and I’ll have to reimport it. I figure it would make a lot of sense to put one in there, since I can’t think of many, if any, games that wouldn’t call for some sort of timer.

All I know is that when I subtract Time.deltaTime from a number for a timer and hold up a stopwatch to compare, my script has usually negated 3-4 seconds before my stopwatch even hits 1 second. So, this is not a very great method of making a timer. Time.deltaTime is only your time in-between frames.

Now, those few seconds wouldn’t matter in most cases… But what about RTS games? Every second counts in those games, and the developer cannot afford to have such a huge offset in time. We need a sure-fire way to keep track of REAL time, not simulated time using Time.deltaTime.

I, for one, am a HUGE RTS fan, and have attempted on several occasions to create an RTS game. One of the biggest turn-offs for me was the inability to keep real time. I am the type of person that can’t sell a product until I know that everything is working efficiently and properly. The time offset of using Time.deltaTime is not proper.

sounds like an asset store oppurtunity

It could be… But in all honesty, all it takes is a quick google search and a copy-pasta job from the internet if you don’t know how to program. Unity doesn’t leave you with many, if any, other options for making a timer other than negating Time.deltaTime from a timer value, so most, if not all, timers look identical. Which… Kind of annoys me because (yes, i’m reiterating myself again) using Time.deltaTime is not accurate!

Vision Timer
$5.00

Works fine for me …

Didn’t know this existed. I’ll probably buy this.

Invoke("stuff",delay);

I have many of classes/tools/utilities that I have written that I use regularly (camera scripts/editor extensions/sprite go modifiers/etc. I export them as an asset bundle and store them in the default unity directory. Anytime I start a new project, I just do Assets>Import Package>BasePackage and they all get imported. It’s great way to re-use stuff, and beats copying them in by hand.

You can use the time since start up or you can access all of the C# System time functions.

System.DateTime endTime;
bool active;
const float TIME_DELTA = 0.01f;  // We could just use 0 but this will enable the event to fire in the frame before the timer expires if the timer is very close to firing.

void Update() {
  if (active) CheckTimer();
}

public void StartTimer(float timeInSeconds) {
  endTime = System.DateTime.Now + TimeSpan.FromSeconds(timeInSeconds);
  active = true;
}

void CheckTimer () {
  if ((endTime - System.DateTime.Now).TotalSeconds  < TIME_DELTA) {
    active = false;
    SendMessage("Boom");
  }
}

Just typed that in the editor so I’m sure there are errors, but hopefully it illustrates the point.


I’m also very very suprised that you are seeing 4 seconds expire in 1 second by decrementing a counter by Time.deltaTime…

Learn about coroutines and WaitForSeconds() - It’ll change your world.

Example:

void Start () {

  StartCoroutine(TimedStuff());

}

 

IEnumerator TimedStuff () {
  //Do some stuff
  
  //Wait for time
  yield return new WaitForSeconds(3.2f);
  
  //Do some other stuff 3.2 seconds later
  
}

You can also do it this way if you want to be able to stop things:

void Start () {
  
  StartCoroutine("TimedStuff");
  
}

void Update () {
  
  if (Input.GetKeyDown("s")) {
    StopCoroutine("TimedStuff");
  }
  
}

IEnumerator TimedStuff () {
  //Do some stuff
  
  //Wait for time
  yield return new WaitForSeconds(3.2f);
  
  //Do some other stuff 3.2 seconds later
  
}

You don’t need a Timer class, as zombiegorilla said :

Everything is here :
http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.Invoke.html
http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.InvokeRepeating.html
Functions of http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.html

+1 Coroutines are increadible

Didn’t actually know about Invoke/Repeat, but looking at those examples I get the impression a Coroutine still gives you way more control, with negligible extra typing

#1 thing about coroutines, AND Invoking with a delay…

I want a GUI-based timer. Something that will let my user know how much time they have left to complete a task.

If I weren’t going to use a GUI-based timer I would either use Invoke, InvokeRepeating, or a Coroutine.

Not sure why you want a Timer class, when the Time class gives you everything you need to do it very easily with minimal code. Just use Time.time to store the start time, then subtract it from the current Time.time when appropriate (e.g. every update or via InvokeRepeating at some interval), use the result for your own needs (e.g. subtract that value from allotted time to complete task) and stuff that result into a guiText.

Then you are doing something wrong somewhere. Whilst there may well be small (mostly negligible) constant difference between using absolute time verses accumulated deltaTime and you have to be careful about your code structure there is no way that you can lose 3-4 seconds.

Just to be sure I tested it and the difference is ever so slight, although if you move the ResetFlag conditional check to the start of Update then you will get a difference of approx deltaTime, which is to be expected since its the time for the last frame.

You also have to take care of when you perform your subtraction (e.g. OnGUI can be called multiple times a frame), while deltaTime is only accurate for the moment that Unity starts a new frame, since any time that then elapses from the start of the frame to the point you check it in say Update is not going to be accounted. Which is why its far better to use absolute time (Time.time) instead.

Also if multiple scripts depend upon the same timings it may be a good idea to have a class that caches any elapsed time or countdowns, since Time.time I suspect will change during the frame as time goes by. Meaning if you perform the same timer code in multiple scripts the actual time elapsed will be accurate to each script but will vary slightly between scripts as their calls to Time.time happen at slightly different times, which depending upon usage may result in slight discrepancies.

Finally you must also take care if you adjust TimeScale, in which case depending upon your requirements you may want to use Time.realtimesincestartup instead.

using UnityEngine;
using System.Collections;

public class TimerTest : MonoBehaviour 
{    
    public float     allottedTime;
    
    private float     startTime;
    private float     timeAccumulalted, timeCountdown;    
    private float     cachedTimeElapsed, cachedTimeLeft, cachedTimeDelta;
    
    private bool    resetFlag = true;
    
    
    void Update () 
    {    
        cachedTimeDelta     = Time.deltaTime;
        
        timeAccumulalted += cachedTimeDelta;
        timeCountdown      -= cachedTimeDelta;
        
        cachedTimeElapsed     = Time.time-startTime;
        cachedTimeLeft        = allottedTime - cachedTimeElapsed;
        
        if(resetFlag) ResetTimer();
    }
        
    void ResetTimer()
    {
        startTime             = Time.time;
        timeAccumulalted     = 0;
        timeCountdown         = allottedTime;
        resetFlag            = false;
    }
        
    void OnGUI()
    {        
        GUILayout.Space(32);
            
        if(GUILayout.Button("Reset")) resetFlag = true;
            
        GUILayout.Label ( cachedTimeDelta                                     + " - Time deltaTime");
        
        GUILayout.Space(8);
        
        GUILayout.Label ( cachedTimeElapsed                                    + " - Time Elpased");
        GUILayout.Label ( timeAccumulalted                                     + " - Time Accumulated");
        GUILayout.Label ( Mathf.Abs(cachedTimeElapsed - timeAccumulalted)     + " - Difference");
        
        GUILayout.Space(8);
        
        GUILayout.Label ( timeCountdown                                     + " - Time Countdown");
        GUILayout.Label ( cachedTimeLeft                                    + " - Time Left");
        GUILayout.Label ( Mathf.Abs(cachedTimeLeft - timeCountdown)         + " - Difference");
    }        
}

Coroutines are simply fantastic, and have a ton of great applications (I am always finding practical use for them, I can’t imagine not using them now). But in the context of this request, (a simple timer), Invoke is the way to go. Coroutines can be used for a simple timer, but kind of overkill.

I see zero point in a Timer class.

As mentioned there is enough functionality in the Time/DateTime classes.

Easy my own timer whit coroutine as Component to the object

using UnityEngine;
using System.Collections;

public delegate void CastedFunction();

public class Progress {
 
 public static void StartNewProgress(GameObject obj, float timeSec, CastedFunction func) {
  Progress.StartNewProgress(obj, timeSec, false, func);
 }
        
 public static void StartNewProgress(GameObject obj, float timeSec, bool repeat, CastedFunction func) {
  if (obj == null) return;
  CorutineLoader prevComp = obj.GetComponent<CorutineLoader>();
  if (prevComp != null) { prevComp.StopAllCoroutines(); prevComp.StartCast(timeSec, repeat, func);}
  else obj.AddComponent<CorutineLoader>().StartCast(timeSec, repeat, func);
 }
 
 private Progress() {}
        
}

public class CorutineLoader : MonoBehaviour {
        
 private float timeSec = 0;
 private bool repeat = false;
 private CastedFunction func = null;
        
 public void StartCast(float time, bool repeat, CastedFunction function) {
  timeSec = time;
  this.repeat = repeat;
  func = function;
  if (timeSec > 0  this.active) StartCoroutine(Corutine());
  else Destroy(this);
 }
        
 private IEnumerator Corutine() {
  yield return new WaitForSeconds(timeSec);
  CastDone();
 } 
        
 private void CastDone() {
  if (func != null) func();
         
  if (repeat  this.active) StartCoroutine(Corutine());
  else { StopAllCoroutines(); Destroy(this);}
 }
 
 private void OnDestroy() {
  StopAllCoroutines();
 }
}

And how to use

using UnityEngine;
using System.Collections;

public class CubeScript : MonoBehaviour {

        private void Start () {
         this.renderer.enabled = false;//DISABLE VISION FOR ONE SECOND
         Progress.StartNewProgress(this.gameObject, 1, CastedFunc);
        }
        
        public void CastedFunc() {
         Debug.LogError("Casted");
         this.renderer.enabled = true;//ENEBALE VISION AFTER ONE SECOND
        }
        
}

I have a notepad file on my desktop that contains pieces of code I usually use. I just copy and paste. Bam. Ain’t nobody got time to rewrite all dem scripts! Also, a timer class would be nice, but I feel like Unity is spoiling us giggle