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 :confused:

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).

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");
		});

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();
 }

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.

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

Lovrenc is absolutely right. The whole scripting runs in a single thread. The Unity API is not thread safe, so you have to call all Unity functions from the main scripting thread (in other words from any callbacks that Unity provides like Update, Start, OnXXXX, … or the coroutine handler which is also called from the same thread).

Coroutines actually do make things not that messy. Have you an example where you have problems to implement a coroutine?

But wouldn’t a coroutine start a new thread? Or do I have the wrong idea about that?

And for an example, how would you do something like that with coroutines?

for(int i = 0; i < 10; i++){
do something
wait(x)
do something
wait(x)
do something
wait(x)
operation x
}

wouldn’t that mean you need 3 coroutines? And if he really works on the main and the coroutine “paralel”, wouldn’t that mean that he runs the operation x without any waiting time so that I would have to start it in an aditional coroutine with a WaitForSeconds(3*x) ?

As I am thinking, Thread.Sleep(x) will stop the tread, so if you created one thread (see System.threading), because high use of processor you can use Sleep inside your threads if you need. If you do System.Threading.Thread.Sleep(1000) you will stop the principal thread (your game will frezzy), you must do sleep in that thread you need, not in your principal process.

I dont know what you want to do, but i wanted to destroy an object after 2 seconds so i did :

flagfordestroy (2f,target);

the function

void flagfordestroy(float timer,GameObject obj){
	todestroy = true;
	objdestroy = obj;
	timedestroy = timer;
}

And at the update function add this

 if (todestroy) {
 timedestroy -= Time.deltaTime; 
 if(timedestroy <= 0){
 	todestroy = false;
 	if(objdestroy)
 		Destroy(objdestroy);
 }
}

You can always adapt that to your code

I wanted to wait x Seconds in the Update() before continuing. So you cannot use the yield there (don’t want to start a coroutine every frame right?)

So if someone, like me, searched this / needs this in and for the Update():

private float timer = 0;

private float timerMax = 0;

void Update ()
{
   text += "Allow yourself to see what you don’t allow yourself to see.";

   if(!Waited(3)) return;

   text += "

Press any key!";
}

private bool Waited(float seconds)
{
    timerMax = seconds;

    timer += Time.deltaTime;

    if (timer >= timerMax)
    {
        return true; //max reached - waited x - seconds
    }

    return false;
}

public static class Util
{
/// Simple timeout function
static public void Timeout( int miliseconds, Action callback )
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += ( object o, System.Timers.ElapsedEventArgs e )=> {
aTimer.Stop();
aTimer.Dispose();
callback();
};
aTimer.Interval = miliseconds;
aTimer.Enabled = true;
}
}
class MyScript : MonoBehaviour
{
void OnEnable()
{
Util.Timer( 500, ()=> {

                Debug.Log( "BAM! " );
                
            } ); 
        }
    }

Invoke and InvokeRepeating.