- Home /
A simple Wait-Function without Coroutine (C#)
Hi guys,
Question says it all. I want to add a wait(x) into my code but without splitting the code withing coroutines, since it would really mess up code with several waits...
So the WaitForSeconds(x) function won't work here. I also tried System.Threading.Thread.Sleep(1000); Unity won't just wait the time but kinda freeze.
I also tried creating own waiting functions that use a while()-loop that checks the time till the start time added to the wait time is reached...same result as the Thread.Sleep.
What is it with Unity and his hate for simple wait functions in combination with C#? Java got the simple yield WaitForSeconds(x)...why won't easy stuff like that won't work in C#? Is there ANY workarround to that? I really don't want to split my code into that damn coroutines :/
Have you tried having a float set to a certain number (amount you want to wait), then when Time.time reaches that, trigger whatever it is you are doing, then set the float to Time.time + whatever wait period you need again? Will put what I mean in an answer. lol.
Yep, I erased it, but it kinda looked like that:
void wait(float x){ t = Time.time; tf = Time.time + x
while(t < tf){ t = t + 0.001; }
}
But that leads to the same result as the Sleep Instruction
See $$anonymous$$ike's answer - Javascript doesn't actually do what you think it does - it's implicitly creating coroutines in the background for you. JS is much more loose about these things than C#, which requires you to explicitly state everything you want to do.
Javascript just does some magic to make the coroutine starting invisible and to remove the need to explicitly define the return type - that's about 20 characters of typing overhead in C#!
Answer by whydoidoit · Jan 13, 2013 at 12:45 AM
I'm a bit confused - you are worried about waiting without coroutines - but then you mention that Javascript (not Java BTW) has yield WaitForSeconds - that means that if you were to do that in Javascript it would be a coroutine!!
The only difference between a function in Javascript with a yield WaitForSeconds and one in C# is that you have to specify that it is a coroutine by returning the IEnumerator type in C# and explicitly start it with StartCoroutine(yourFunction()) unless it is already a Start, OnCollisionEnter etc in which case Unity does that for you.
So:
function DoSomething()
{
DoThingOne();
yield WaitForSeconds(1);
DoThingTwo();
}
Is the same as:
IEnumerator DoSomething()
{
DoThingOne();
yield return new WaitForSeconds(1);
DoThingTwo();
}
And what happens if you want to delay a return value?
For example I want something simple as
int getNumber(){ wait(x) return y; }
How can I do something like that without global variables? And I don't know if C# uses pointer.
No but you can't do that in Javascript either. When would the thing being returned get continued - it doesn't work that way. Your best bet is to use a lambda function and a closure to act on your return value.
int a = 100;
StartCoroutine(DoSomethingInAWhile(a, value=>{
//value is the new value of a
Debug.Log(value.ToString());
});
...
IEnumerator DoSomethingInAWhile(int a, Action<int> onComplete)
{
a = a + DoFirstThing();
yield return new WaitForSeconds(1);
a = a + DoSecondThing();
yield return new WaitForSeconds(2);
onComplete(a);
}
Thank you guys very much for your explanations. I can't say that I am completly happy about the way it is, but at least I understand now why it won't work the way I' used to, and that means a lot =) Have a good night, day or what ever it is in your timezone at the moment^^
Yeah :) Happy to help...
Closures at least mean that you can continue writing code that accesses the local variables in the calling function when the coroutine is complete - but the syntax is funky until you get used to it!
I threw together a couple of tutorials on Unity Gems concerning threads and coroutines.
Answer by pixel_fiend · Jun 24, 2014 at 04:45 AM
This solution obfuscates the Coroutine, and uses Actions, which are generic callback functions.
Make a base class for your scripts that extends MonoBehavior. This will allow use of Coroutine.
using UnityEngine;
using System.Collections;
using System;
public class ExtendedBehavior : MonoBehaviour {
public void Wait(float seconds, Action action){
StartCoroutine(_wait(seconds, action));
}
IEnumerator _wait(float time, Action callback){
yield return new WaitForSeconds(time);
callback();
}
}
Then, in ExtendedBehavior classes, you can use Wait.
Wait (5, () => {
Debug.Log("5 seconds is lost forever");
});
What do you mean by "ExtendedBehavior classes" ? How do I include that in a $$anonymous$$onobehavior class?
Great solution! The coroutine modularity with an Action is perfect to trigger events.
Nice solution - for the beginners out there: include the using System;
within the top section to make sure that the right namespace is available.
Answer by Lovrenc · Jan 13, 2013 at 12:30 AM
I might be wrong but i think unity is running on single thread. If you type
System.Threading.Thread.Sleep(1000);
you would essentialy stop your game from doing anything for 1 secong (aka FPS = 0).
You will either have to use coroutines (its not really that messy, you just have to get used to it) or have a variable that holds your "sleep time" and manualy sum Time.deltaTime to it etc.. (messy and slower).
When I did that it froze unity. And I had not saved yet. Thanks.
it froze because this did not just delay the script for a second. it delayed the whole computer meaning you only had a chance to exit playmode every 1 second. this id not what i needed. i want to freeze just one script. thanks for trying though.
Answer by Carlos900 · Sep 22, 2019 at 06:45 PM
I have a simple code for this.
public float timeToWait = 0.5f;
public float done = 0.0f;
void Update() {
if(Time.time > done) {
done = Time.time + timeToWait;
doSomething();
}
}
I hope I helped you.
Answer by Julien-Lynge · Jan 13, 2013 at 12:39 AM
Unity runs all of the frame events (e.g. Update) in the main Unity thread, so there is no way to sleep one method being called from Update, OnGUI, etc. without sleeping Unity as a whole. As for creating your own 'waiting functions', this will have the same result - Unity has to wait for events to end before it can move on, so Unity will simply freeze. If you think about it, this is logical: Unity has to ensure that the user is done doing everything they're going to do in a frame before they move on to rendering the frame and starting the next frame. This is the difference between a frame-based rendering engine and something like Java.
Without knowing what exactly you want to do, and why you want to do it, I'll have to take a couple guesses.
First off, you can certainly implement threads within Mono/.NET, and there are numerous articles on doing so. However, you should be warned that you can't access anything Unity specific (e.g. change a component) from outside the main Unity thread. Once you have your own managed threads, you can sleep to your heart's content.
If you need to have access to Unity functions and you want to sleep a method, you have to use IEnumerators. You don't, however, have to use Coroutines, and it sounds like you're fed up with trying to manage them (I don't much care for them either). In that case, I have good news: there's an excellent solution called TaskManager that was created by a user named chomp. It acts like coroutines (e.g. it doesn't block the main Unity thread) but gives you a lot more control over execution. You can find it here:
http://forum.unity3d.com/threads/94220-A-more-flexible-coroutine-interface
Your answer
Follow this Question
Related Questions
Help with waiting / coroutine c# 1 Answer
Wait inside method until user action 3 Answers
C# Coroutine help 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers