Waiting for seconds in Update()

Since you can’t use “yield new WaitForSeconds()” in the Update() function what is the best way to make something pause for 1 second instead of firing off every frame?

Thanks

1 Like
  1. don’t use update. it will be called on each frame
  2. Use Startcoroutine and start it in “Start”. Make it yield for a second or whatever timeframe you want

Right. I understand that but the problem is that I need to run it when a touch happens on the iPhone so it needs to run from update().

2 Likes

Something like this?

private bool beingHandled = false;

public void Update()
{
    if( /*some case  */ !beingHandled )
    {
        StartCoroutine( HandleIt() );
    }
}

private IEnumerator HandleIt()
{
    beingHandled = true;
    // process pre-yield
    yield return new WaitForSeconds( 1.0f );
    // process post-yield
    beingHandled = false;
}
12 Likes

Ive tried this. Here is my code… Can anyone see why it’s not waiting and just keeps counting down as fast as the frames?

function ReduceFuel(){

	while(FuelLevel > 1)
	{
		
		FuelLevel -= 1;
		yield new WaitForSeconds(1);
		
	}	

}

function Update () {
		
	
	for (var evt : iPhoneTouch in iPhoneInput.touches)
	{
		
		var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
		
		
			if (evt.phase == iPhoneTouchPhase.Stationary)
			{

						if(element == ArrowUp || element == ArrowDown)
						{	
							
								ReduceFuel();
								
						}
				
			}
}

The reason that isn’t working as you’d expect is that ReduceFuel isn’t running as a coroutine. As AngryAnt suggested, you should start it as a coroutine:

StartCoroutine(ReduceFuel());

I was thinking a coroutine was just a function. Whats the difference between a coroutine and a function?

I think it is one of these

A coroutine is a function which will be continuously executed over several frames - depending on how you yield it. All coroutines are executed after the last update call and when you yield, the function ends - only to be re-run from the point of the yield statement once the yield statement has been “completed”.

1 Like

I’m using Javascript and not C#. I think I remember reading in the docs that you had to call co-routines for C# but that Javascript automatically would do this when you call a function.

Have a look at the script reference (my best friend) for information on coroutines and the yield statement. At the bottom of the page it says:

So you do need to use StartCoroutine when calling from Update.

Ok, I did this and still get the same result:

			if (evt.phase == iPhoneTouchPhase.Stationary)
			{

						if(element == ArrowUp || element == ArrowDown)
						{	
							
								StartCoroutine(ReduceFuel());
								
						}
				
			}

[/quote]

I guess I should have put all the code…this is what I have now and it still does not waitforseconds…wierd…

function ReduceFuel(){

	while(FuelLevel > 1)
	{
		
		FuelLevel -= 1;
		yield new WaitForSeconds(5);
		
	}	

}

function Update () {
	
		
	//PlayWarnings();		
	
	for (var evt : iPhoneTouch in iPhoneInput.touches)
	{
		
		var element : GUIElement = guiLayer.HitTest (Input.mousePosition);
		
		
			if (evt.phase == iPhoneTouchPhase.Stationary)
			{

						if(element == ArrowUp || element == ArrowDown)
						{	
							
								StartCoroutine(ReduceFuel());
								
						}
				
			}

}

Since you’re using JScript, you should drop the new keyword in your WaitForSeconds line:

yield WaitForSeconds(5);

You only need new in C# code (where yield statements get rather complicated).

I’ve actually used the keyword new throughout my entire game and it’s worked as i’ve wanted it too. I went ahead and tried it without it as you suggested and it still isn’t working … any other suggestions?

Not with Javascript, where it does that for you. The only reason to use StartCoroutine in Javascript is if you want to be able to use StopCoroutine on the routine you’re starting.

–Eric

Thats what I sorta remembered reading… Eric, do you have any suggestions to pull this off? It seems like anything I call in Update() acts as if it were in Update().

What I’m trying to accomplish is a steady fuel consumption as long as the button is being pushed.

What you probably want to do is multiply the amount by Time.deltaTime so that you get a constant rate regardless of frame rate. You can do this inside the Update function:

fuelLevel -= Time.deltaTime * ratePerSecond;

As for the issue of coroutines, JScript and Update, there is a discrepancy in the documentation. The description for StartCoroutine does clearly state that:

Yet the overview does say to use StartCoroutine to start a function from Update to use a yield statement. There is some issue here, hopefully Eric or one of the Unity gods has an answer!

Good thought…problem is, I’ve tried that too and it doesn’t work either. I plugged your code and tried again using various ratesPerSecond and no matter what it is the numbers still count down per frame.

:frowning:

Is there any other part of your code that accesses fuelLevel? If you set the ratePerSecond to 0.2, that would be the same as 1 unit per 5 seconds, but you’ll see it drop continuously while the button is pressed. You’re saying that you press the button and it is dropping at a rate of 1 unit per frame?