- Home /
Pausing an Invoke for a time
I'm coding a game that's 70% done, and now I'm doing the pause system. All loops and updates have an if(isPaused) to them, and works very nice.
However, in many places there is an Invoke("Something", delay), like on weapon cooldowns and unit respawning. But when I pause, I can't use Time.timeScale = 0 because the pause menu animation depends on it.
Does anyone know a way to pause or delay an Invoke until the game is unpaused, without using the timeScale or reimplementing the Invoke system? I'm really running out of ideas here. :/
There are a lot of questions on UA about pausing your game. You should search the site before asking.
http://answers.unity3d.com/questions/7544/How-do-I-pause-my-game.html
$$anonymous$$ust be able to help you because it has so many correct answers.
The link provided in the last comment is a good one, you should check it out. But in response to your specific case, I would use a coroutine ins$$anonymous$$d of invoke(). With a coroutine, you could decrease a counter every frame, and then call the function you wanted when that counter reached zero. The salient different is that you can make it so the counter only goes down when the game is un-paused, by checking your isPaused var. something like the code below should work
IEnumerator my_function_wraper(float delay){
while(true){
if(delay>0){
if(unPaused)
delay-=time.deltatime;
}
yeild return;
continue;
}
else{
myfunction();
yeild break;
}
}
}
Disclaimer: I just typed in this code right now, so it may have some errors, but the general idea is there. If you are new to coroutines, check out this page
http://docs.unity3d.com/Documentation/$$anonymous$$anual/Coroutines.html
If you have to make this change for many different functions, you could make one method (lets call it pause_safe_invoke) that worked like the one above, but then use delegates so you can change what function gets called. Good page on delegates here
http://msdn.microsoft.com/en-us/library/vstudio/ms173172.aspx
This is an interesting question. None of the answers at the link @Jamora provided address it, nor have I seen a fix for this specific problem. I don't know how you are doing your menu animation, but one possibility is to recode it to use Time.realTimeSinceStartup rather than deltaTime. This would allow you to set Time.timeScale to 0.
@mattmanj17 seems to have the more elegant solution. if you didn't want to go through and change all of your code, you could have a "pause" call CancelInvoke("$$anonymous$$ethod") which will stop your invokes.
Then you could add in coroutines from mattman17's solution to count how much time had passed since the invoke was called, but before it executed, and on unpause call Invoke("$$anonymous$$ethod", remainingDelayTime).
So, this is a really sloppy way of doing it. I can't really recommend it. But it's possible that you might be able to just add the little bit of functionaly to your code, rather than completely rewriting everything. It's also entirely possible that the Invoke ti$$anonymous$$g might differ from the coroutine ti$$anonymous$$g. So it depends on how precise your ti$$anonymous$$g needs to be.
I've seen the link, it really has many good answers. But I know many of them, and the best one involves recoding the menu system. Not that it would be wrong, but it would be creating work for someone else other than me (the guy who built the entire menu system).
mattmanj17's solution is a good one, but creating a corroutine in every script with an Invoke could be too heavy, especially since the game is already CPU intensive, so it needs testing. I like the idea of doing the same idea globally, managing all Invokes, but could be too much work (and prone to errors).
I think I will make the public message OnPause() and OnUnpause(), like the link said, and save the starting and pause times of Invoke methods, and calculating the delay if necessary. Once I get it running (or any other system), I'll post as an answer.
Answer by devang024 · Jun 07, 2015 at 09:28 AM
Late to the party, but here's the after party stuff.
public void prepareForPlay() {
if (isPaused == false) {
/*Game's meat*/
}
else
{
StartCoroutine(asyncPrepareForPlay());
}
}
IEnumerator asyncPrepareForPlay()
{
yield return !isPaused;
prepareForPlay ();
}
and this "prepareForPlay" function is called with Invoke("prepareForPlay",5.0f) somewhere, so when prepareforplay is called and game is paused(isPaused==true), it will go to coroutine and will not call that function until isPaused is FALSE. I Hope it helps.
Answer by FreshTofu · May 09, 2018 at 12:55 AM
You could also set your animation to unscaled time in the inspector window under the animator component. Im late, however this could be for anyone who may be reading this in the future. :)
Your answer
Follow this Question
Related Questions
Can you lerp an object when Time.timeScale = 0? 1 Answer
Pause game that not using deltatime for movment 1 Answer
Pause button 2 Answers
Pause menu doesn't pause everything 0 Answers