A better introduction to yield/coroutines?

Does anyone know a website/resource to learn more about yield and coroutines in Unity3D? The online documentation isn’t too much of a help when you are away from Unity itself to test the examples and see the results.

I found several threads on the topic, but they covered very specific problems.

What exactly would you need introduction wise thats not covered in the docs (for example WWW) and a plentitude of resources that contain them?

They just fire off an run async but in the same thread and are used for functions that “need to wait for a result” (polling) like waiting for WWW for example.

No magic behind it or anything complex as they are limited to StartCoroutine → yield for whatever reason and timeframe you need → done :slight_smile:

I would be happy about some more basic examples and some “real life” application possibilities.

Reading a text file from the web, into a string in iOS would be fantastic.

You mean something like the following (untested)

void Start ()
{
  StartCoroutine(DownloadText("http://www.google.com/#sclient=psy-ab&q=unity3d"));
}

IEnumerator DownloadText (string url)
{
  WWW request = new WWW(url);
  yield request;
  Debug.Log ("The result was: " + request.text);
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Test : MonoBehaviour {
	
	private List<string> urls = new List<string> ();
	private List<Texture2D> images = new List<Texture2D> ();
	private int X = 0;
	
	// Coroutine
	IEnumerator Start () {
		urls.Add ("https://g1.gstatic.com/android/market/com.iUnity.angryBots/hi-256-3-99dff454687064ca78dcbf9b576f02bd17823d57");
		urls.Add ("http://www.unitytheband.com/presskit/assets/images/unity-icon.png");
		urls.Add ("http://the3dninja.com/blog/wp-content/uploads/2010/02/modo2Unity.jpg");
		yield return new WaitForSeconds (1);
		StartCoroutine ("ImageLoader");
		StartCoroutine ("ImageLoader2");
	}
	
	// Coroutine
	IEnumerator ImageLoader () {
		foreach (string url in urls) {
			WWW w = new WWW (url);
			yield return w;
			images.Add ((Texture2D) w.texture);
		}
		OnAllLoaded ();
	}
	
	void OnAllLoaded () {
		X = 0;
		foreach (Texture2D t2d in images) {
			GameObject go = GameObject.CreatePrimitive (PrimitiveType.Plane);
			Material mat = new Material (Shader.Find ("Diffuse"));
			mat.mainTexture = t2d;
			go.renderer.material = mat;
			go.transform.position = new Vector3 (X, 0, 0);
			go.transform.eulerAngles = new Vector3 (90,180,0);
			go.transform.localScale = new Vector3 (0.2F, 1.0F, 0.2F);
			X = X + 2;
		}
	}
	
	// Coroutine
	IEnumerator ImageLoader2 () {
		yield return new WaitForSeconds (5);
		X = 0;
		foreach (string url in urls) {
			WWW w = new WWW (url);
			yield return w;
			ShowImage ((Texture2D) w.texture);
		}
	}
	
	void ShowImage (Texture2D image) {
		GameObject go = GameObject.CreatePrimitive (PrimitiveType.Plane);
		Material mat = new Material (Shader.Find ("Diffuse"));
		mat.mainTexture = image;
		go.renderer.material = mat;
		go.transform.position = new Vector3 (X, 2, 0);
		go.transform.eulerAngles = new Vector3 (90,180,0);
		go.transform.localScale = new Vector3 (0.2F, 1.0F, 0.2F);
		X = X + 2;
	}
}

I see.

here’s another practical example:

var attackRate : float = 0.5;

private var isAttacking : boolean;

function Update(){

	if(Input.GetButtonDown("Fire1")  !isAttacking){
		StartCoroutine(Attack());
	}

}

function Attack(){
	isAttacking = true;
	animation.CrossFade("attack");
	yield WaitForSeconds(animation["attack"].length);
	//send damage raycast, instantiate projectile, spawn hit particles
	//or whatever here, so they coincide with the end of the attack animation
	yield WaitForSeconds(attackRate); //time allowed between attacks
	isAttacking = false;
}

That looks like a good example to me. Is the Update() function paused until the Attack() function has finished?

No, Update() and Attack() will be running concurrently. You can’t pause Update. The trick in that code is you can only spawn an Attack() coroutine with a mouse click when isAttacking is false, and isAttacking will be true if an Attack() coroutine is running, so multiple clicks won’t spawn more coroutines until the last one is finished.

See, now that makes sense to me. :slight_smile: Thanks for the explanation. I think I can use this in my current code somewhere.

Can we get that same example in C# please?

mine and appels are C#

one important thing about coroutines that is rarely mentioned ( though i think people assume so ) if the game object of the script or the script component itself gets destroyed all coroutines running off it just stop executing.

I often find myself making a game object just for running coroutines that are not tied to any direct object.

Also one thing that i learned too late with c# is if you yield return null it waits a frame. Because i didn’t know this i would often use WaitForEndOfFrame but its not the same. You should only use WaitForEndOfFrame in cases where you need all the scripts in the scene to update prior to the coroutine resuming. The other thing about it is anything that evaluates to null will cause a wait one frame. So say if you had some function that returned a coroutine or yieldinstruction and would return null when it shouldnt wait. You have to check if its null or not before yield returning it unless you want it to wait a frame. The only way functionally to get past this is to make a coroutine from a ienumerator that looks like this:
IEnumerator DoNotWait() { yield break; }

So to sum up: to wait a frame in c#

yield return null;

js is just

 yield;

An interesting, if not wholly useful fact is that you can reuse YieldInstructions:

YieldInstruction wait = someBool ? new WaitForSeconds(10f) : StartCoroutine(SomeOtherFunction());
while(true)
{
Debug.Log("Test");
yield return wait;
}

That code will print Test every 10 seconds if someBool is true, or while wait on a function if it’s false. It allows you to pass around YieldInstructions as objects and yield on them regardless of what they are. Useful, I guess for a queue system that will wait a specific time before checking for more work if there is no work to do.

This is not correct, they do never, ever, run concurrently.

This is true, but you should program as if they would and avoid cases where relying on one coroutine to update prior to another.

No it is not true!
Unity runs all code you write within a single thread, as such its technically totally impossible to run it concurrently (this includes coroutines which are just asyncronously executed functionality within the same thread) without you explicitely using Threads, which can not access anything that extends from UnityEngine.Object without crashing unity and the player

Yea, what i was saying is even though its not multi threaded and never runs concurently you should not write coroutine code that rely’s on other coroutines or even update functions. You never know what coroutine is going to execute first without a lot of planning and generally you should not have two coroutines setting a value on a member which run at the same time. You do not have to worry about thread safety, but you should be very careful about what your doing within a coroutine in regards to other coroutines or the scripts Update functions.

That is true, although its not concurrent, its not deterministic either so “good guessing” normally gives you one thing and thats “being good fucked up”.

And don’t forget that you can’t debug it either as with any async stuff, at least not in a meaningfull way.

Use the observer pattern and ‘event firing’ when you have dependencies and need multiple things to happen basing on some state or alike changing, never make coroutines wait on ‘status updates’ of other coroutines, you will lose the war, for granted!

EDIT: or just invest in PlayMaker in such a case, thats to design state machines and thats the so far only case I’ve seen where totally unmanageable ‘coroutine dependency chains’ appeared, trying to solve a state machine problem the coroutine bruteforce way.