- Home /
Yield WaitForSeconds outside of time.Scale
When I call yield WaitForSeconds(Time) in my script and time.Scale is 0.0 it will never finish yielding. Is there a way to make WaitForSeconds run outside of time.Scale, say continue to make it run at time.Scale 1.0?
EDIT: What I was actualy looking for is when you press a button the game pauses (Time.Scale 0.0) and the Gui displays. I however need to use a yield statement while the gui is on and Time.Scale is 0.0 to display another GuiTexture after the yield but I can't do this because yield WaitForSeconds uses Time.Scale for the seconds. So what I am asking for is if there is a way to yield WaitForSeconds but not with the seconds using the time.scale which is 0.
EDIT[2013] I have moved on to more complex projects and I am not really working with Unity at the moment. If anyone else is still having this problem or has any questions I think they should still be able to ask in the comments. Otherwise I think that this question can be closed. I actually don't have the time to check if any of the answers work right now. Still I would like to thank you guys for reviving this question :). I'm pretty sure that I would now be able to solve it myself as I am a bit more experienced then I was when I asked the question. Still, thanks for the help.
Answer by mathiassoeholm · Dec 06, 2013 at 01:55 PM
You could make a utility method like this
public static class CoroutineUtil
{
public static IEnumerator WaitForRealSeconds(float time)
{
float start = Time.realtimeSinceStartup;
while (Time.realtimeSinceStartup < start + time)
{
yield return null;
}
}
}
And then use it like this
private IEnumerator MyCoroutine()
{
// Do stuff
yield return StartCoroutine(CoroutineUtil.WaitForRealSeconds(DURATION));
// Do other stuff
}
Found this just now, works perfectly. Thank you very much!
$$anonymous$$an! Thank you tons! I have having a rough time with this! :)
Answer by hannesdvl · Nov 10, 2016 at 10:48 AM
WaitForSecondsRealtime was added in Unity 5.4
IEnumerator MyCouroutine(float waitTime)
{
yield return new WaitForSecondsRealtime(waitTime);
//DO STUFF
}
This is What i Wanted, Works Perfectly Thanks $$anonymous$$an
Answer by benni05 · Jun 27, 2013 at 10:54 AM
You can also use this trick like this:
IEnumerator wait5sec() {
float start = Time.realtimeSinceStartup;
while (Time.realtimeSinceStartup < start + 5f) {
yield return null;
}
// do what you like
}
I tried to use the while
command before, but it blocks the execution of the entire game until the while condition has been reached.
Answer by Alex_95 · Jun 19, 2016 at 12:42 PM
@Catlinman, you can use CustomYieldInstruction for this.
public sealed class WaitForRealSeconds : CustomYieldInstruction
{
private readonly float _endTime;
public override bool keepWaiting
{
get { return _endTime > Time.realtimeSinceStartup; }
}
public WaitForRealSeconds(float seconds)
{
_endTime = Time.realtimeSinceStartup + seconds;
}
}
Now you can use it like this:
private IEnumerator CustomCoroutine()
{
//your stuff
yield return new WaitForRealSeconds(1.0f);
//your other stuff
}
Answer by mgreene1 · Feb 29, 2016 at 04:32 AM
To put this problem to bed (hopefully):
K, so here's how I fixed this. In my game, I have ranged weapons. I picked up an excellent tip from a game design tutorial; a good bit of feedback is to cause a fraction of a second of a pause to your game (say, 40 ms) when your projectiles impact enemies. Your eyes won't register the pause, but your brain will, making impacts register a little better.
But I digress.
The point is that I wanted to add a complete pause to all game play for 40 ms every time a significant bit of feedback occurs (you hit an enemy, the enemy dies, an explosion occurs, etc). I tried to use
StartCoroutine(Function());
_IEnumerator Function()
{
//setting timescale to 0 will crash your game, but such a lower number is basically the same thing ^_^-b
Time.timeScale = .001f;
yield return new WaitForSeconds(.004f);
Time.timeScale = 1f;
}
This does not work. It has something to do with how CoRoutines work and how they are updated not every frame or something blah blah blah. I'm not a CS engineer; I'm a game designer. Luckily, I heard from another post that the mst accurate timer in Unity (maybe not true, correct me pls) is InvokeRepeating("StringFunctionName", [time until start], [repeat rate]).
Armed with this new knowledge, I solved it like so:
void OnCollisionEnter2D(Collision2D col)
{
string objectCollidedWith = col.collider.gameObject.tag;
if (objectCollidedWith != "Player")
{
//If it collided with an enemy
if (objectCollidedWith == "Enemy")
{
//lots of designer magic
//calls for my desired "pause"
ProjectileSleep();
//ACCURATELY waits .004ms to undo my pause. Works like a charm! I multiply the .004ms by timeScale //or else it will take longer than you want it to. The repeat here doesn't matter because the bullet //destroys itself before it can occur.
InvokeRepeating("WakeUp", .004f * Time.timeScale, 1F);
}
}
void ProjectileSleep()
{
//starts the "pause"
Time.timeScale = .001f;
//check to make sure it's happening
Debug.Log (Time.timeScale);
}
void WakeUp()
{
//return timeScale to normal
Time.timeScale = 1f;
// And destroy the bullet, ez peasy
DestroySelf();
}
I hope this can be referenced as a possible solution to this pain in the ass that is working in real time with CoRoutines and slow motion/pausing.
Keep designing, true believers! Excelsior!
Your answer
Follow this Question
Related Questions
Why Is yield return new WaitForSeconds() not working 2 Answers
Definition of Script.function() depends on Script.function()... 3 Answers
Script gets stuck on WaitForSeconds() 1 Answer
yield WaitForSeconds waits for too long. 2 Answers
Yield and WaitForSeconds not stopping at correct points? 1 Answer