How can I make a C# Method wait a Number of Seconds?

How do I make a specific Method (function) in my C# script simply wait a number of seconds?

I’m not using an Update() function and I’d rather not. In JS there’s a method called Yield I think that does it. How does one do it in C#??!?!

Thanks!

1 Like

You call the function you want to pause through StartCoroutine and then use yield return new WaitForSeconds(…) or whichever yield you need in it

2 Likes

Thanks, Dreamora, I think you’ve got me going in the right direction, but I need the c# syntax that will work.

Could you or someone throw me some actual code for that?

thanks.

1 Like

It’s throwing this error:

Assets/Scripts/Processor.cs(53,14): error CS1624: The body of Processor.Process(string)' cannot be an iterator block because void’ is not an iterator interface type

so do I have to make a separate function??!?

:smile:

The function needs to return IEnumerator, not void and yes you need another function!

You should go check out the wiki, it explains this stuff pretty good :slight_smile:

public class MyScript : MonoBehaviour
{
    void Start()
    {
		StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        //This is a coroutine
        DoSomething();
        
         yield return 0;	//Wait one frame
   
         DoSomethingElse();
    }
}

[/code]

3 Likes

yes you must make it an extra function.
you cant yield update (neither can unityscript, it just pretends to but in reality it likely splits the function apart at the yield creating a new coroutine which it calls and immediately yields)

Okay, it’s a little squirrely…

I wrote it as a separate function called Wait():

	    IEnumerator Wait(float duration)
    {
        //This is a coroutine
       Debug.Log("Start Wait() function. The time is: "+Time.time);
		Debug.Log( "Float duration = "+duration);
         yield return new WaitForSeconds(duration);   //Wait
		Debug.Log("End Wait() function and the time is: "+Time.time);
    }

which is called from within the Process() function like this:

			Debug.Log("Process() function calling Wait function at "+Time.time);
			Debug.Log("procDuration is "+procDuration);
		StartCoroutine(Wait(procDuration));
			Debug.Log("Process() function after returning from the Wait Function, the time is:"+Time.time);

The debug log reads this way:

Process() function calling Wait function at 3.290453
procDuration is 1.5
Start Wait() function. The time is: 3.290453
Float duration = 1.5
Process() function after returning from the Wait Function, the time is:3.290453

then the debug log goes on to show a lot of other stuff going on in the Process function and elsewhere, then after 1.5 seconds, it spits this out:

End Wait() function and the time is: 4.802543

So what is happening here is that the Wait function immediately returns to the Process function, but stalls at the line “yield return new WaitForSeconds(duration);” before going on.

Perhaps I can work my code around that, but I was hoping to stall the Process function itself by ‘duration’ number of seconds.

Is there any way to do that?

Thanks for the detailed explanations!

you can not stall the calling function unless its an IEnumerator itself which will not work for update (would be useless anyway as update is called once per frame independent if the previous one finished or not)

to wait on a coroutine, you would use yield return StartCoroutine(…) if you call it from within a coroutine.

and reworking the logic is trivial as mentioend. just transfer all after the yield into a new function with return IEnumerator, then move the yield to the beginning of that function and in update where you had the yield, start the coroutine and the nreturn.

I think you may need to figure out how the Timer class works in C#.

Or simply,

public static void MyDelay( int seconds )
{
  TimeSpan ts = DateTime.Now + TimeSpan.FromSeconds( seconds );

  do {} while ( DateTime.Now < ts );
}

Thanks, Kenny, I’ll give that a whirl!

Dreamora: I don’t have an Update function, I’m not sure why you keep talking about Update functions and what I can’t do from Update.

There is no Update.

doh, overread the “not” in your initial posting, thats why.

though the rest still applies: Function that wants to pause must itself be a coroutine, and transforming a non-coroutine to one you can yield in the middle is basically a matter of adding in place of the yield line :wink:

  StartCoroutine(OtherHalf());
}

IEnumerator OtherHalf()
{

I say basically cause there is one thing that will require a few words more and that is if you have local variables in the original functions that are needed in the other half. but you can just specify parameters in OtherHalf and transfer them too. instance and class variables don’t need to be sent as they are accessable

Kenny,

using that loop crashes my computer instantly. This is the function:

			endTime = Time.time + procDuration;		
			
			Debug.Log("Process() function calling Wait function at "+Time.time);
			Debug.Log("procDuration is "+procDuration);
			Debug.Log("Time.time = "+Time.time+", endTime = "+endTime);

do {} while ( Time.time < endTime ); 
			
			//StartCoroutine(Wait(procDuration));
			Debug.Log("Process() function after returning from the Wait Function, the time is:"+Time.time);

It doesn’t even print ANYTHING in the debug log at all! It just freezes up! WTF?!

It was a good idea, but it just ain’t happening.

Maybe the compiler doesn’t like the empty do while loop at runtime.

Kk, Dreamora, thanks for the help. I think I can make that work by either making the variables global or passing them from function to function. I can do that!

I’m going to sleep on it… There may be some other things to consider.

Thanks you two!

Stand corrected,

public static void MyDelay(int seconds)
{
	DateTime dt = DateTime.Now + TimeSpan.FromSeconds(seconds);

	do { } while (DateTime.Now < dt);
}
1 Like

Kenny, idk why but it just doesn’t work properly. That freezes everything up for the duration in seconds. It puts the whole program on pause while it waits. No updates execute, it stops ALL scripts!

Idk what’s up.

perhaps it’s because the function is static and is in a single threaded program. You may try to add the codes instead of calling a static method,

DateTime dt = DateTime.Now + TimeSpan.FromSeconds(seconds);

do { } while (DateTime.Now < dt);

If it doesn’t, then you may need to work on the Timer class, as the Timer class works on its own CPU thread.

Why can’t you simply use a coroutine?

What are you doing?

I know that this thread is old, but I just start with Unity and I want to give an answer to all who see this thread.

First of all, it is not the same thing to do a passive wait than an active wait. Doing what KennyW suggest (do … while) is an active wait that consumes CPU.
Using WaitForSeconds function is a passive wait that does not consumes CPU.

The reason why Vimalakirti can not get his code works is because the method that really waits is not that who initiates the call but the call itself. So, notice the result of the following code:

void Start ()
{
  Debug.Log (string.Format("Start time = {0}", Time.time));
  StartCoroutine("CreaIEspera");
  Debug.Log (string.Format("Time before call CreaIEspera = {0}", Time.time));
}

IEnumerator CreaIEspera()
{
  for (int iCnt = 0; iCnt < numDaus; iCnt++) 
  {
    yield return new WaitForSeconds(3f);
    Instantiate (theCube, position.transform.position, position.transform.rotation);
    Debug.Log (string.Format("Timer before a cube creation = {0}", Time.time));
  }
}

Start time = 0
UnityEngine.Debug:Log(Object)

Time before call CreaIEspera = 0
UnityEngine.Debug:Log(Object)

Timer before a cube creation = 3.016229
UnityEngine.Debug:Log(Object)

Timer before a cube creation = 6.021845
UnityEngine.Debug:Log(Object)

Timer before a cube creation = 9.027622
UnityEngine.Debug:Log(Object)

The thing is that when we call a method using StarCoroutine, the unity calls and immediately returns, thats why the Start time and the time before the call CreaIEspera is 0.
Once the program is executing the CreaIEspera function, it waits 3 seconds for each loop in the for.

P.S.: Another important point, do not concatenate strings with +, use auxiliary calls as string.Format… they are more efficient.

1 Like

I was just nosying by and thought I’d clarify an issue within this thread, the reason that method freezes unity is because it wont return until the while method completes, so effectively you lock up the main thread until that function returns. Hope this helps! :slight_smile:

Thanks its working… .