Time.time only returning 0

I’m trying to spawn enemies on a cool down using Time.time, however Time.time is always 0, meaning my program never enters the if statement on line 15.


6950825--817787--upload_2021-3-18_21-16-50.png

I use the same system to give the enemies a cool down on their attacks, which works exactly as intended.


The spawn enemy script is attatched to the game manager, where as the enemy damage script is attatched to an enemy. Not sure if that makes a difference.

Is there a limitation with this method with Time.time that im not aware of? I’ve tried using coroutine, but I haven’t been able to wrap my head around them and get it to work for this purpose.



Update runs once per frame, and the entire update method will run during the same frame. So your whole while loop (all 4 iterations) all happen during the same frame. Time.time is only updated once at the beginning of the frame. Essentially, while you’re within one frame in Unity, time is effectively frozen. Time.time will not increase until the next frame. And rightly so.

If you’re trying to do something spaced out over time, you should either use a coroutine, or use your own float time which you increment by Time.deltaTime each frame until it reaches the point when you want to do the next action.

3 Likes

In addition to what was already mentioned, if Time.time doesn’t advance it means your game is effectively frozen / crashed. Any while loop must be completed before your game can reach the next frame. However, if you do happen to need the actual time elapsed during the same frame (like for benchmarking etc.) you can use Time.realtimeSinceStartup - but using that won’t solve your problem, because the game would still be frozen as implemented. Try something akin to…

private float spawnElapsed = 0;
private float spawnInterval = 1;
void Update()
{
  spawnElapsed += Time.deltaTime;
  while (spawnElapsed >= spawnInterval)
  {
    spawnElapsed -= spawnInterval;
    SpawnEnemy();
    enemyCount++;
  }
}

private float fireElapsed = 0;
private float fireInterval = 0.25f;
void Attack()
{
  fireElapsed += Time.deltaTime;
  if (fireElapsed >= fireInterval)
  {
    // todo: fire projectile
    fireElapsed = 0;
  }
}

The first example spawns however many are needed immediately in order to catch up.
The second example fires when cooldown has elapsed, then resets cooldown, with no catching up.
Untested - hope it helps.

Edit: fixed whatever in example

Edit: …and what I mean by “to catch up” is that lets say you had an interval of 0.5 seconds, but 2 seconds passed before another update, all 4 instances would spawn immediately after the 2 seconds, so there’s just as many spawning regardless of framerate or missed intervals.

1 Like

Both of the above are key to understanding timing in Unity. When your code is running, Unity is frozen solid.

The only exception is coroutines.

Here is some interesting timing diagram info to help you visualize your place in the mechanism:

https://docs.unity3d.com/Manual/ExecutionOrder.html

You can also use Invoke() and InvokeRepeating(). Repeating does what it says. Invoke only does it once, but you can call the same method again recursively, so you can change the repeat rate over time.
There are also coroutines, which offer more flexibility than these.

As far as understanding things,Imvoke is merely a shortcut telling Unity to create a coroutine for you. So all you have to know is that coroutines check just after each Update to see if they are ready yet. That way your only decision is whether you want to learn to write coroutines, or if you can use a shortcut for now (you could call Invoke 4 times with increasing delays, for example. Ugly, but works). Or, you can always use Update with a little bit of work (something like if(Time.time>nextSpawnTime) { nextSpawnTime=Time.time+1.0f; ...)