Like described in this tutorial, you can just launch a process and keep it going for as long as the script exists like this:
while (true)
{
// wait for X seconds
yield WaitForSeconds(Random.Range(minTypeChange, maxTypeChange));
// do something
SwapType();
}
But can I use this structure if I need to pause the game? In other words can the waiting time’s process be paused somehow too? I know I can easily just replace this whole thing by using my own timers or probability factors and ditch the whole WaitForSeconds, but since Unity offers this kind of a method too, I would like to know if using timers instead would be bad or inefficient practice. Any comments?
It all really depends on how you pause the game. Don’t worry about bad or inefficient practice, do what works, the more time you spend worrying if what you’re doing is right is less time you spend on your game. If it works, it’s right.
Having said that, WaitForSeconds is affected by time scale which I’m assuming you already tested before posting this as it would only take a few seconds to test, so this brings me to the question how exactly are you planning on implementing your pausing system?
FYI, you can yield to a new coroutine if you’re wanting to pause a time based block using a custom timer:
static class GameTimer {
private static double gameTimeElapsed;
/// assume bunch code for tracking time here...
public static IEnumerator Wait(double seconds)
{
var releaseTime = gameTimeElapsed + seconds;
while (gameTimeElapsed < releaseTime) {
yield return null; // wait 1 frame then check the time again...
}
}
}
So if you pause in GameTimer it’ll continue to wait until time is resumed. Yield return null waits a single frame. Shouldn’t need to worry about the performance overhead as you generally don’t have a time based wait happening on thousands of objects at once.
public IEnumerator Foo()
{
Debug.Log("Wait for 4 in-game seconds regardless of pausing");
yield return StartCoroutine(GameTimer.Wait(4d));
Debug.Log("4 in-game seconds later...");
}
Yeah, that’s probably true. I think I’ll just go with the method that doesn’t involve WaitForSeconds.
I did check into that option but I quite quickly realized that wouldn’t do as I don’t want to stop all time-dependent activity. Otherwise setting timescale to 0 does work well and is an easy solution for many things.
Hmm… I don’t think I got the point of this example. How does this differ from yield waitforsecs? Yield waitForSecs keeps waiting if timescale is set to zero, so did you mean something else by “if you pause in GameTimer”?
By the way, would float have too little precision, so is it better to use double in general for timers like in your example?
Any way, thanks for the comment and on the effort with the code!
The point is that it doesn’t differ so you can use your own custom timer instead of relying on Unity’s Time.deltatime and timescale stuff which isn’t always flexible enough to meet everyone’s needs. I usually have a few custom timers, one that I use for game time, another real time and some that I create and discard when needed, all of which I sometimes want to yield Wait() and pause independently when needed at different times.
And yes, float precision is crap for timers. Well, it’s enough for deltas that span less than a few minutes but for measuring elapsed time for a game that might right a few hours or sit paused for a day it’s woefully inaccurate. I really wish Unity wouldn’t use floats in their timers.