Starting and stopping while loops?

How do I start and stop while loops? I’m trying to create a car dashboard with working turn signal lights and lever. When the lever is in left turn signal position, the left turn light should blink. When the lever is in right turn signal position, the right turn light should blink. When the lever is in off/center position, the turn lights should be off.

804849–29644–$lever02.js (1.6 KB)

I am not sure I would use a while loop for this scenario. Maybe others can say for sure, but it is my belief that while x is true, a while loop will be called like an update, alot, in a little amount of time. As such, for a basic blicker which might go on and off at a rate of every half sencond say, in that time, if while is looping it will have been called 30 000 times to the once required for the blink.

I would use a yield.

example being

function turnOnBlinker ()
{
if(blinking == true) //var used to turn on blinking
yield WaitForSeconds(0.5);
turnOffBlinker();
}

function turnOffBlinker ()
{
if(blinking == true) //var used to turn on blinking
yield WaitForSeconds(0.5);
turnOnBlinker();
}

then if you want this loop to stop just set var blinking to false.

A while loop checks to see if the condition in parenthesis is true, if the condition becomes false the loop will break, here is an example in C#.

int i=0;

while(i<5)
{
Console.WriteLine(“The value of i is “+i+”\n”)
i++;
}

This would output to the screen :

The value of i is 0

The value of i is 1

The value of i is 2

The value of i is 3

The value of i is 4

then when i becomes 5 the loop stops.

and as I was saying that will happen very quickly. Maybe a 1000th of a second.

That’s infinite recursion, and will eventually crash since the stack isn’t infinite. A while loop would be much preferable. However, you can use InvokeRepeating:

var blinkInterval = .5;
private var blinker : Light;

function Blink () {
    blinker.enabled = !blinker.enabled;
}

To use it,

blinker = leftBlinker; // or whatever
InvokeRepeating("Blink", .01, blinkInterval);

Use CancelInvoke to make it stop. You could use a coroutine, along with StartCoroutine and StopCoroutine,

function Blink () {
    while (true) {
        blinker.enabled = !blinker.enabled;
        yield WaitForSeconds(blinkInterval);
    }
}

You could also set a boolean to true/false to make the loop stop instead of using while(true) and StopCoroutine. However InvokeRepeating is simpler for this sort of thing anyway.

–Eric

Coroutines.

public enum BlinkerState { Off, Left, Right };
private BlinkerState blinker = BlinkerState.Off
void Update()
{
    if (blinker == BlinkerState.Left)
    {
        StartCoroutine(DoLeftBlinker());
    }
    else if (blinker == BlinkerState.Right)
    {
        // you get the idea
    }
}

private IEnumerator DoLeftBlinker()
{
    while (blink == BlinkerState.Left)
    {
        LeftBlinkerOn();
        yield return new WaitForSeconds(0.5f);
        LeftBlinkerOff();
        yield return new WaitForSeconds(0.5f);
    }
}

How so? (crash) it is a simple do this…wait…do that. If this is false return, end cycle.

You don’t end the cycle if its false, you just call the other function without the yield…

Each function gets shoved on to the stack effectively waiting for the called function to exit.

Run it and unity will crash in a few seconds once you turn a blinker off.

Even if you fixed that if you left a blinker on for long enough it will still crash for the same reason … it will just take bit longer due to all the 0.5s waits.

But if blinking becomes false, in my example, the cycle will end.

It doesn’t! it just calls the other function without a yield.

You could add a few braces to make it end, but even then its not nice… what if someone leaves the blinker on!

I use UnityScript, not C#. I think that the code written by KelsoMRK is in C#.

renman-

if (blinking == true)
yield WaitForSeconds();
turnBlinkerOne();

will recurse infinitely but

if (blinking == true){
yield WaitForSeconds();
turnBlinkerOn();
}

will not. You missed some curly braces.

jeffmorris - I don’t use UnityScript but the code should be about the same. It was really just an example to get you started.

That will start a new coroutine every frame in Update. Really for this it’s just simpler to use InvokeRepeating. Checking states constantly in Update isn’t very efficient either; better to just call a function only when you need it.

–Eric

You’re right - I rushed through that. InvokeRepeating is the better solution.

I still have problems. I tried Eric’s code.

806047–29724–$lever02.js (1.25 KB)

I got it working - I had to use C# instead of UnityScript.

There’s no reason you’d have to use C#. The problem is that you can’t Invoke a coroutine; the yield in the Blink function is unnecessary and prevents it from working. The point of InvokeRepeating is that it repeats at the specified interval, you don’t use loops and yield.

–Eric