yield WaitForSeconds don't delay my code.

Hi UnityFriends,

I having a little problem with my code that make feel like a idiot…

What im trying to do here with my code is a menu. I i press positive Vertical Debug the position where it is, same with the negative vertical.

Now, my problem started with the velocity in that my vertical control is moving so i decided to delay it with yield WaitForSeconds but looks like is not working or stg is wrong with my code.

private var position = 1 ;

function Update () {

	if(Input.GetAxis("Vertical")<0)
	{
		if(position == 4)
		{
			position = 1;
			Menu();
		}
		else{
			position += 1;
			Menu();
		}
	}
	else if(Input.GetAxis("Vertical")>0)
	{
		if(position==0)
		{
			position = 3;
			Menu();
		}
		else
		{
		position -= 1;
		Menu();
		}
	}

}

function Menu()
{
	switch(position) {

		case 1:
			Debug.Log("Arcade");
			Wait();
		break;
		case 2:
			Debug.Log("2 Players");
			Wait();
		break;
		case 3:
			Debug.Log("Network");
			Wait();
		}
}

function Wait()
{
	yield WaitForSeconds(5);
}

Any other idea to help me fix my problem will be welcome :slight_smile:

thanks

Your code does wait, you’re simply constantly calling the same subroutines on each frame : Update → Menu → Wait. Without some sort of boolean flags controlling the routine calls, you won’t get the desired result.

Instead of using yield to control the speed, expose your position incremental values as variables on the global level, multiply them by Time.deltaTime to become frame rate independent and tweak the values until you get he desired speed.

if you are trying to put some kind of delay instead why not try making the button that you are trying to delay less responsive? or not so sentitive? like going to edit > project settings>input and find the one you want to mess with.
somethings don’t always have to be done in code.

Thanks for the help Divine, that have sense.

But i still with the same speed problem.

here the update.

private var position = 1 ;
var speed =0.1;

function Update () {

var VerticalSpeed = (Input.GetAxis("Vertical")* speed * Time.deltaTime);

	if(VerticalSpeed<0)
	{
		if(position == 4)
		{
			position = 1;
			Menu();
		}
		else{
			position += 1;
			Menu();
		}
	}
	else if(VerticalSpeed>0)
	{
		if(position==0)
		{
			position = 3;
			Menu();
		}
		else
		{
		position -= 1;
		Menu();
		}
	}

}

function Menu()
{
	switch(position) {

		case 1:
			Debug.Log("Arcade");
		break;
		case 2:
			Debug.Log("2 Players");
		break;
		case 3:
			Debug.Log("Network");
		}
}

This isn’t what I explained, and now I understand what you’re trying to do. You need to use boolean flags as such:

private var position = 1 ;
private var canSelect : boolean = true;

function Update () {

    if(Input.GetAxis("Vertical") == 1  canSelect)

    {

        if(position == 4)

        {

            position = 1;

            Menu();

        }

        else{

            position += 1;

            Menu();

        }

    }

    else if(Input.GetAxis("Vertical") == -1  canSelect)

    {

        if(position==0)

        {

            position = 3;

            Menu();

        }

        else

        {

        position -= 1;

        Menu();

        }

    }

 

}

 

function Menu()

{
    canSelect = false;
    switch(position) {

 

        case 1:

            Debug.Log("Arcade");

        break;

        case 2:

            Debug.Log("2 Players");

        break;

        case 3:

            Debug.Log("Network");
        break;

        }
        yield WaitForSeconds(5);
        canSelect = true;

}

Ohh, I see. you control it with “canSelect” good one :slight_smile:

i figure that work better with (Input.GetAxis("Vertical") >0 canSelect)

Thank you for your big help Diviner :wink:

GetAxis only returns 3 values at any given time, -1, 0 and 1. There’s no need to check for greater or less when you know the values you get.

checked! you are right, just i have to set the wait speed to a lower value.

btw, im replace the Debug.Log("Arcade"); for

GameObject.Find("b1b").SetActiveRecursively(false);
GameObject.Find("b1g").SetActiveRecursively(true);

where what i want to do here is hide a GameObject and Show Other Game object.

And im getting this error

NullReferenceException
UnityEngine.GameObject.SetActiveRecursively (Boolean state) (at C:/BuildAgent/work/842f9557127e852/Runtime/ExportGenerated/Editor/UnityEngineGameObject.cs:224)
menu+$Menu$3+$.MoveNext () (at Assets/menu.js:48)
UnityEngine.MonoBehaviour:StartCoroutine_Auto(IEnumerator)
menu:Update() (at Assets/menu.js:16)

What can be the problem?

Most probable cause is that the objects b1b and b1g aren’t instantiated when you call them. Instead of trying to make use of them as soon as you find them, store them in a variable and check if they exist before you activate / deactivate them :

var thisObject : GameObject = GameObject.Find("b1b");
if(thisObject) thisObject.SetActiveRecursively(false);

This way you protect yourself from null reference exceptions.

Thanks Divine, how it works properly :slight_smile:

but stuck a bit when pass from the position 1 to the 3 or form the 3 to the 1.

Can be the reason this part of the code?

if(position == 4)
{
position = 1;
Menu();
}

Why not use InvokeRepeating to set how often you wish to call some code?

Unity - Scripting API: MonoBehaviour.InvokeRepeating - it has a second parameter to specify WHEN to start calling it, for example 5 seconds delay before it will start calling, and a 3rd parameter to specify how often to call it.

Change your Update function to this :

function Update () {

     if(Input.GetAxis("Vertical") == 1  canSelect) {
           position++;
           if(position > 3) position = 1;
           Menu();
      } else if (Input.GetAxis("Vertical") == -1  canSelect) {
           position--;
           if(position < 1) position = 3;
           Menu();
      }
}