This document explains in detail how JSBinding supports Unity Coroutine in JavaScript.
First, I suggest you read this page to understand coroutine scheduling:
http://wiki.unity3d.com/index.php/CoroutineScheduler
and also Yield instructions in Mozilla SpiderMonkey engine:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield
OK, let‘s get started. Open this scene:
Assets/JSBinding/Samples/Coroutine/TestCoroutine.unity
Part 1. Usage
This is source code of TestCoroutine.cs:
1 [JsType(JsMode.Clr,"../../../StreamingAssets/JavaScript/SharpKitGenerated/JSBinding/Samples/Coroutine/TestCoroutine.javascript")] 2 public class TestCoroutine : MonoBehaviour { 3 4 // Use this for initialization 5 void Start () 6 { 7 StartCoroutine(DoTest()); 8 } 9 10 // Update is called once per frame 11 void Update () 12 { 13 14 } 15 void LateUpdate() 16 { 17 jsimp.Coroutine.UpdateMonoBehaviourCoroutine(this); 18 } 19 IEnumerator WaitForCangJingKong() 20 { 21 yield return new WaitForSeconds(2f); 22 } 23 IEnumerator DoTest() 24 { 25 // test null 26 Debug.Log(1); 27 yield return null; 28 29 // test WaitForSeconds 30 Debug.Log(2); 31 yield return new WaitForSeconds(1f); 32 33 // test WWW 34 WWW www = new WWW("file://" + Application.dataPath + "/JSBinding/Samples/Coroutine/CoroutineReadme.txt"); 35 yield return www; 36 Debug.Log("Text from WWW: " + www.text); 37 38 // test another coroutine 39 yield return StartCoroutine(WaitForCangJingKong()); 40 Debug.Log("Wait for CangJingKong finished!"); 41 } 42 }
This is JavaScript code compiled by SharpKit:
1 if (typeof(JsTypes) == "undefined") 2 var JsTypes = []; 3 var TestCoroutine = { 4 fullname: "TestCoroutine", 5 baseTypeName: "UnityEngine.MonoBehaviour", 6 assemblyName: "SharpKitProj", 7 Kind: "Class", 8 definition: { 9 ctor: function (){ 10 UnityEngine.MonoBehaviour.ctor.call(this); 11 }, 12 Start: function (){ 13 this.StartCoroutine$$IEnumerator(this.DoTest()); 14 }, 15 Update: function (){ 16 }, 17 LateUpdate: function (){ 18 jsimp.Coroutine.UpdateMonoBehaviourCoroutine(this); 19 }, 20 WaitForCangJingKong: function (){ 21 var $yield = []; 22 $yield.push(new UnityEngine.WaitForSeconds.ctor(2)); 23 return $yield; 24 }, 25 DoTest: function (){ 26 var $yield = []; 27 UnityEngine.Debug.Log$$Object(1); 28 $yield.push(null); 29 UnityEngine.Debug.Log$$Object(2); 30 $yield.push(new UnityEngine.WaitForSeconds.ctor(1)); 31 var www = new UnityEngine.WWW.ctor$$String("file://" + UnityEngine.Application.get_dataPath() + "/JSBinding/Samples/Coroutine/CoroutineReadme.txt"); 32 $yield.push(www); 33 UnityEngine.Debug.Log$$Object("Text from WWW: " + www.get_text()); 34 $yield.push(this.StartCoroutine$$IEnumerator(this.WaitForCangJingKong())); 35 UnityEngine.Debug.Log$$Object("Wait for CangJingKong finished!"); 36 return $yield; 37 } 38 } 39 }; 40 JsTypes.push(TestCoroutine);
See "DoTest" and "WaitForCangJingKong" method, they are coroutine methods. SharpKit translates C# yield to a $yield array, and every yield instruction is pushed into that array.
BUT, this is not JavaScript yield syntax. So, I made a menu to correct this: JSB | Correct JavaScript Yield code
After excuting this menu, the 2 methods look like:
1 WaitForCangJingKong: function* (){ 2 yield (new UnityEngine.WaitForSeconds.ctor(2)); 3 }, 4 5 DoTest: function* () { 6 UnityEngine.Debug.Log$$Object(1); 7 yield (null); 8 UnityEngine.Debug.Log$$Object(2); 9 yield (new UnityEngine.WaitForSeconds.ctor(1)); 10 var www = new UnityEngine.WWW.ctor$$String("file://" + UnityEngine.Application.get_dataPath() + "/JSBinding/Samples/Coroutine/CoroutineReadme.txt"); 11 yield (www); 12 UnityEngine.Debug.Log$$Object("Text from WWW: " + www.get_text()); 13 yield (this.StartCoroutine$$IEnumerator(this.WaitForCangJingKong())); 14 UnityEngine.Debug.Log$$Object("Wait for CangJingKong finished!"); 15 }
Do you notice what has been changed?
- Use "function*" instead of "function" to declare a coroutine function
- "$yield" array has been deleted
- "$yield.push" has been replaced with simple "yield"
Now the code matchs exactly JavaScript yield syntax, and is ready to run.
Part 2. Things inside
A C# coroutine method is compiled by C# comipler, it returns an IEnumerator when you call it.
This IEnumerator is then passed to "StartCoroutine" method. After that, it is Unity coroutine scheduler who manages them and decides when to call "MoveNext".
In the case of JavaScript, it also has compiler to compile coroutine function, but C# coroutine scheduler is not