do-while WTF?

A lot of people say that the do-while construct is not supported in UnityScript. I didn’t know that, so I wrote this code to test why I was getting wierd results.

function Start () {

  var count = 0;
  do {
    print("do-while(true): " + count++);
    yield;
  } while(true);
  
  count = 0;
  do {
    print("do-while(false): " + count++);
    yield;
  } while(false);
  
}

To my surprise, the result I got was:

do-while(true): 0
do-while(false): 0
do-while(false): 1
do-while(false): 2
do-while(false): 3
...

:shock:

So now it’s supported, but the condition evaluation is inverted? I’d rather get a syntax error than this kind of behaviour.

behaves much more like repeat - until, perhaps some “syntactic mixup” on top of it.

That was before Unity 3.2. http://unity3d.com/unity/whats-new/unity-3.2.html

That’s not what happens though. I copy/pasted your code, and do/while(true) runs forever as expected. I suspect you’re actually running a different version of the code.

–Eric

I’m using computers with Unity 3.2 and 3.3. The changelog for 3.4 says

http://unity3d.com/unity/whats-new/unity-3.4.html

Man, I hate having to use UnityScript.

PS: 2 versions to fix a feature that never worked lol

I tried using a do-while piece in a script a little while ago. It crashed unity…this was on 3.4 pro

If it crashed Unity, it’s because you made an infinite loop - not because of a problem with do-while.

Yea any loop which does not exit will crash unity. This includes stuff like properties which gets call the set or functions which call themselfs, or while/do-while/for

I used the “yield” statement just to avoid the infinite loop crash.

try using instead a yield WaitForEndOfFrame()

Not necessary; just “yield” is fine. The problem comes when using an infinite loop with no yield at all, which is not the issue in this topic.

I actually tested the code earlier in 3.2 and it worked fine, however I neglected to recompile it. Interestingly it works in 3.2 as long as you don’t recompile the scripts. Indeed it’s 3.4 that has real proper support.

–Eric

I use a basic do while script as my AI for most all of my constructs. It seems to work fine, they change stare with out crashing unity at all. I also use yield.

whats the c# equivalent to yield; ?

yield return null ?

yep.

intresting… what does that do exactly? is it the same as waitforendofframe?

It waits for the next frame.

–Eric

AFAIK:

void Update(){}

and

IEnumerator myUpdate() {
        while (true) {
            yield return null;
        }
    }

Are functionally identical. Of course, with the coroutine you can do cooler stuff :slight_smile:

Thats great, feel dumb finding that out just now.

This is an example of yield script for a basic FSM ai, but it helps to use a cool down when you have multiples of these going

IEnumerator StartFSM()
    {
        while (true)
        {
            switch (state)
            {
                case State.StartUp:
                    StartCoroutine(StartUp());
                    break;
                case State.CheckPlayersTowers:
                    CheckPlayerTower();
                    break;
                case State.CheckResources:
                    CheckResources();
                    break;
                case State.CheckMyTowers:
                    CheckMyTowers();
                    break;
            }
            yield return new WaitForSeconds(coolDown);

Probably it was a bug in the UnityScript compiler backend. I didn’t look the CLI generated, but I guess that it was using the wrong instruction in the condition evaluation.

If you translate the code to C# the compiler will warn you about unreachable code after the first do-while, so it’s safe to say that was a compiler bug.

Removing the “yields” I got this (with Unity 3.2):

.method public hidebysig virtual instance void 
        'Start'() cil managed
{
  // Code size       107 (0x6b)
  .maxstack  6
  .locals init (int32 V_0,
           int32 V_1,
           int32 V_2)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  br         IL_002f
  IL_0007:  ldstr      "do-while(true): "
  IL_000c:  ldloc.0
  IL_000d:  dup
  IL_000e:  stloc.1
  IL_000f:  ldc.i4.1
  IL_0010:  add.ovf
  IL_0011:  dup
  IL_0012:  stloc.0
  IL_0013:  pop
  IL_0014:  ldloc.1
  IL_0015:  box        ['mscorlib']'System'.'Int32'
  IL_001a:  call       string ['Boo.Lang']'Boo.Lang.Runtime'.'RuntimeServices'::'op_Addition'(string,
                                                                                              object)
  IL_001f:  call       void ['UnityEngine']'UnityEngine'.'MonoBehaviour'::'print'(object)
__[B]  IL_0024:  ldc.i4.1
  IL_0025:  brfalse    IL_002f
[/B]__  IL_002a:  br         IL_0035
  IL_002f:  ldc.i4.1
  IL_0030:  brtrue     IL_0007
  IL_0035:  ldc.i4.0
  IL_0036:  stloc.0
  IL_0037:  br         IL_0064
  IL_003c:  ldstr      "do-while(false): "
  IL_0041:  ldloc.0
  IL_0042:  dup
  IL_0043:  stloc.2
  IL_0044:  ldc.i4.1
  IL_0045:  add.ovf
  IL_0046:  dup
  IL_0047:  stloc.0
  IL_0048:  pop
  IL_0049:  ldloc.2
  IL_004a:  box        ['mscorlib']'System'.'Int32'
  IL_004f:  call       string ['Boo.Lang']'Boo.Lang.Runtime'.'RuntimeServices'::'op_Addition'(string,
                                                                                              object)
  IL_0054:  call       void ['UnityEngine']'UnityEngine'.'MonoBehaviour'::'print'(object)
__[B]  IL_0059:  ldc.i4.0
  IL_005a:  brfalse    IL_0064[/B]__
  IL_005f:  br         IL_006a
  IL_0064:  ldc.i4.1
  IL_0065:  brtrue     IL_003c
  IL_006a:  ret
} // end of method 'NewBehaviourScript1'::'Start'

:roll_eyes: