"while" in Unity iPhone "Match" Example

Why is the raycasting in the Unity iPhone “Match” Example in a “while (true)/yeild;” loop not in function “Update()”?

while (true) 
{
	// Use Raycast to pick cards that have mesh colliders attached...
 
	var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
 
	if (Input.GetMouseButtonDown (0))
	{
		if (Physics.Raycast (ray, hit, 100)) 
		{
			if (! matchOne)
			{
				revealCardOne();
			}
			else
			{
				yield revealCardTwo();
				if (cardsLeft == 0) 
				{
					yield gameWon();
				}
			}
		}
	}
 
	timeLeft = timeTotal - Time.time;
	timeGUI.text = "" + timeLeft;
 
	if (timeLeft <= 0) 
	{
		yield gameLost();	
	}
 
	// Wait for next frame
	yield;
}

141630–5180–$cardselection_152.js (3.62 KB)

because while true never returns, this basically means that you have infinite update functions running after a short period of time because update does not care if the previous call to update has finished or not, it will just call a new one.

Dre -

Not sure I completely understand.

This infinite while loop just seems to mimic the function Update().

Doesn’t function Update() get called just as regularly?

Since this is just a loop to check to see if someone has touched the screen, and if so then DoSomething(), why not just put this code in function Update() rather than make it’s own infinite while()/yield loop?

It’s probably because you can’t yield in Update(), so this allows more control over scripting motion. I have a similar loop in the player movement script’s Start function in Realmaze3D:

	while (true) {
		var move = CheckAxis();
		if (move != 0) {
			yield Walk(move);
		}
		if (turnDirection != TurnDirection.None) {
			yield Turn(turnDirection, turnSpeed);
		}
		
		yield;
	}

This is because movement is from square to square instead of free movement. turnDirection is checked in Update, so the player can initiate a turn at any time, which is actually executed when any potential forward/backward movement is finished, and likewise you can’t move until the turn is finished.

–Eric

VERY NICE!

And only for £0.59!

I'll have to try it out! (~.^)

But to the task at hand…

Am I incorrect in thinking that the final yield; without any time parameter (eg: yield WaitForSeconds(n.n); etc.) means that it will only wait one frame?

or do I misunderstand what yield?

(unfortunately all of the examples under “file:///Applications/Unity%20iPhone/Documentation/ScriptReference/YieldInstruction.html” and it’s children all have time parameters in the yield line…)

Yep, that’s correct. So basically

while (true) {
   yield;
}

is equivalent to Update().

–Eri

You are in a maze of twisty little passages: Up
You are in a twisty maze of little passages: Left
You are in a little twisty maze of passages: Sigh

RealMaze.Unity3D!

Little Angel feels he’s back where he started.

“Ok. Kewl.”

I don’t really need to know the answer to this, as I am researching GUI/Raycasting/TouchPhase things… but it did catch my eye.

the main difference is that update is called every frame again, which adds overhead over function that just runs and runs and runs …
Also update is framerate dependent, while above solution basically “just runs at a fixed rate”

No, it’s still framerate dependent. When you’re waiting for the next frame, the frame time varies just as much whether you’re using yield or Update. Also, “while (true)” has just as much overhead as Update.

–Eric

I use a lot of coroutines for the game flow structure, like showing the intro, the main game loop, gameover, etc.

E.g. (c# code, just an example)

IEnumerator Start()
{
	yield return StartCoroutine(FadeIn());

	yield return StartCoroutine(ShowGameIntro());
	while (!KeyPressed())
	{
		yield return new WaitForEndOfFrame();
	}
	yield return StartCoroutine(HideGameIntro());
	
	yield return new WaitForSeconds(1);
	
	yield return StartCoroutine(GameLoop());
	
	yield return StartCoroutine(ShowGameover());
	while (!KeyPressed())
	{
		yield return new WaitForEndOfFrame();
	}
	yield return StartCoroutine(HideGameover());
}

When I build it this way the flow of the game is very linear and easy to read and adjust. If I was to put it in an Update() function, I would have to create a big ugly switch case structure which would be much more error prone (forgot to put in the correct state change, variables that need to keep track of how many times / seconds it was shown, etc.).

Coroutines make building your flow so much easier (especially animating dialogs). I love using it for tasks like these.

gr.jakko