91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

用C#寫的協程轉換成JavaScript后無法正常工作怎么辦

發布時間:2021-12-18 10:25:22 來源:億速云 閱讀:160 作者:iii 欄目:大數據

本篇內容主要講解“用C#寫的協程轉換成JavaScript后無法正常工作怎么辦”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“用C#寫的協程轉換成JavaScript后無法正常工作怎么辦”吧!

先說結論吧:用C#寫的協程轉換成 JavaScript 后,無法正常工作,必須要手動修改一點點代碼。

以下是 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 }

這是 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);

注意看 DoTest 函數和 WaitForCangJingKong 函數,他們都是協程函數。SharpKit 對其中的 yield 代碼翻譯成一個 $yield 數組,每一個 yield 指令都加到 $yield 數組中。

這樣使得我們無法與 JavaScript 的 yield 對接。這就是為什么協程編譯成 JavaScript 代碼后無法直接使用的原因。

目前,需要做點小修改就可以運行了,以下是修改過的 JavaScript 文件:

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 
22             yield (new UnityEngine.WaitForSeconds.ctor(2));
23 
24         },
25         DoTest: function* (){
26 
27             UnityEngine.Debug.Log$$Object(1);
28             yield (null);
29             UnityEngine.Debug.Log$$Object(2);
30             yield (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 (www);
33             UnityEngine.Debug.Log$$Object("Text from WWW: " + www.get_text());
34             yield (this.StartCoroutine$$IEnumerator(this.WaitForCangJingKong()));
35             UnityEngine.Debug.Log$$Object("Wait for CangJingKong finished!");
36 
37         }
38     }
39 };
40 JsTypes.push(TestCoroutine);

需要修改的有:

  1. 協程函數改用 function* 定義

  2. 刪除 $yield 數組的定義以及協程函數最后的返回

  3. 將 $yield.push 替換為 yield 。

===================================================

2015/07/13 22:18 更新,目前已經把這個替換工作做到菜單了,菜單是 JSB | Correct JavaScript Yield code

這個菜單會嘗試替換所有在 JSBindingSetting.jsDir 目錄下的所有 JavaScript 文件。你只需要在編譯 SharpKit 工程后運行一下這個菜單即可,如果有錯誤會給出提示,如果沒錯,代碼應該可以正常使用了!

目前這個方案算是比較完美了。

用C#寫的協程轉換成JavaScript后無法正常工作怎么辦

下面講一講原理。

當我們在 C# 中使用 MonoBehaviour.StartCoroutine 函數時,傳遞給他代表協程函數的 IEnumerator(后面簡稱 IE)。之后是由 Unity 內部決定何時調用 IE.MoveNext()。而這部分的源代碼我們是無法得到的。

在 JavaScript 端寫了一個模擬 Unity 功能的協程管理器。文件是:

StreamingAssets/JavaScript/Manual/UnityEngine_MonoBehaviour.javascript

(后面簡稱 B)。

這里順便提一下,當你導出 MonoBehaviour 類時,會產生

StreamingAssets/JavaScript/Generated/UnityEngine_MonoBehaviour.javascript

文件,簡稱A。B 和 A 的關系是,在includes.javascript 中,包含順序是先 A 后 B,B重寫了一些 A 的函數,并增加了一些內部函數。目前重寫的函數只有 StartCoroutine$$IEnumerator 和 StartCoroutine$$String。增加的函數有 $UpdateAllCoroutines,$updateCoroutine等等,這些就是協程管理器的內容。以下貼出代碼(可能不是最新的):

1 _jstype = undefined;
  2 for (var i = 0; i < JsTypes.length; i++) {
  3     if (JsTypes[i].fullname == "UnityEngine.MonoBehaviour") {
  4         _jstype = JsTypes[i];
  5         break;
  6     }
  7 }
  8 
  9 if (_jstype) {
 10     _jstype.definition.StartCoroutine$$String = function(a0/*String*/) { 
 11         if (this[a0]) 
 12         {
 13             var fiber = this[a0].call(this);
 14             return this.$AddCoroutine(fiber);
 15         }
 16     }
 17     _jstype.definition.StartCoroutine$$IEnumerator = function(a0/*IEnumerator*/) { 
 18         return this.$AddCoroutine(a0);
 19     }
 20 
 21     //
 22     // Coroutine Scheduler
 23     // 
 24     // REFERENCE FROM
 25     // 
 26     // Coroutine Scheduler:
 27     // http://wiki.unity3d.com/index.php/CoroutineScheduler
 28     //
 29     // JavaScript yield documents:
 30     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield
 31     // 
 32 
 33     // fiber 類似于 C# 的 IEnumerator
 34     _jstype.definition.$AddCoroutine = function (fiber) {
 35         var coroutineNode = {
 36             $__CN: true,  // mark this is a coroutine node
 37             prev: undefined,
 38             next: undefined,
 39             fiber: fiber,
 40             finished: false,
 41 
 42             waitForFrames: 0,          // yield null
 43             waitForSeconds: undefined, // WaitForSeconds
 44             www: undefined,            // WWW
 45             waitForCoroutine: undefined, // Coroutine
 46         };
 47 
 48         if (this.$first) {
 49             coroutineNode.next = this.$first;
 50             this.$first.prev = coroutineNode;
 51         };
 52 
 53         this.$first = coroutineNode;
 54         // NOTE
 55         // return coroutine node itself!
 56         return coroutineNode;
 57     }
 58 
 59     // this method is called from LateUpdate
 60     _jstype.definition.$UpdateAllCoroutines = function (elapsed) {
 61         // cn is short for Coroutine Node
 62         var cn = this.$first;
 63         while (cn != undefined) {
 64             // store next coroutineNode before it is removed from the list
 65             var next = cn.next;
 66             var update = false;
 67 
 68             if (cn.waitForFrames > 0) {
 69                 cn.waitForFrames--;
 70                 if (cn.waitForFrames <= 0) {
 71                     waitForFrames = 0;
 72                     this.$UpdateCoroutine(cn);
 73                 }
 74             }
 75             else if (cn.waitForSeconds) {
 76                 if (cn.waitForSeconds.get_finished(elapsed)) {
 77                     cn.waitForSeconds = undefined;
 78                     this.$UpdateCoroutine(cn);
 79                 }
 80             }
 81             else if (cn.www) {
 82                 if (cn.www.get_isDone()) {
 83                     cn.www = undefined;
 84                     this.$UpdateCoroutine(cn);
 85                 }
 86             }
 87             else if (cn.waitForCoroutine) {
 88                 if (cn.waitForCoroutine.finished == true) {
 89                     cn.waitForCoroutine = undefined;
 90                     this.$UpdateCoroutine(cn);
 91                 }  
 92             }
 93             else {
 94                 this.$UpdateCoroutine(cn);
 95             }
 96             cn = next;
 97         }
 98     }
 99 
100     _jstype.definition.$UpdateCoroutine = function (cn) { // cn is short for Coroutine Node
101         var fiber = cn.fiber;
102         var obj = fiber.next();
103         if (!obj.done) {
104             var yieldCommand = obj.value;
105             // UnityEngine.Debug.Log$$Object(JSON.stringify(yieldCommand));
106             if (yieldCommand == null) {
107                 cn.waitForFrames = 1;
108             }
109             else {
110                 if (yieldCommand instanceof UnityEngine.WaitForSeconds.ctor) {
111                     cn.waitForSeconds = yieldCommand;
112                 } 
113                 else if (yieldCommand instanceof UnityEngine.WWW.ctor) {
114                     cn.www = yieldCommand;
115                 }
116                 else if (yieldCommand.$__CN === true/*yieldCommand.toString() == "[object Generator]"*/) {
117                     cn.waitForCoroutine = yieldCommand;
118                 }
119                 else {
120                     throw "Unexpected coroutine yield type: " + yieldCommand.GetType();
121                 }
122             }
123         } 
124         else {
125             // UnityEngine.Debug.Log$$Object("cn.finished = true;");
126             cn.finished = true;
127             this.$RemoveCoroutine(cn);
128         }
129     }
130 
131     _jstype.definition.$RemoveCoroutine = function (cn) { // cn is short for Coroutine Node
132         if (this.$first == cn) {
133             this.$first = cn.next;
134         } 
135         else {
136             if (cn.next != undefined) {
137                 cn.prev.next = cn.next;
138                 cn.next.prev = cn.prev;
139             }
140             else if (cn.prev) {
141                 cn.prev.next = undefined;
142             }
143         }
144         cn.prev = undefined;
145         cn.next = undefined;
146     }
147 }

目前支持的 yield return 后面可接的類型有:

  1. yield return null; // 下一幀調用 MoveNext()

  2. yield return new WWW(...); // WWW

  3. yield return new WaitForSeconds(...); // 等待一定時間

  4. yield return new StartCoroutine(...); // 串連另一個協程

 C# 協程和 JavaScript 協程有一個區別:C#是協程初始就調用了 MoveNext(),JavaScript 需要初始調用 next() 才能和 C# 匹配(現在沒有調用,因為一幀的時間也挺快的,效果差不多一樣)。

另外,看前面的 C# 代碼有這樣的代碼:

1 void LateUpdate()
2 {
3      jsimp.Coroutine.UpdateMonoBehaviourCoroutine(this);
4 }


現在因為我們自己要管理協程,所以需要有一個 Update 入口。如果想讓 JavaScript 協程正常工作,必須在某個地方調用協程管理器的 Update。現在我是把他放在 LateUpdate 函數中,如果你想換地方,也是可以的。

在 C# 中,jsimp.Coroutine.UpdateMonoBehaviourCoroutine 函數并不做任何事情,只有當運行 JavaScript 版本時,才有做事情。JavaScript 的實現是在這個文件中:

StreamingAssets/JavaScript/JSImp/Coroutine.javascript

1 if (typeof(JsTypes) == "undefined")
 2     var JsTypes = [];
 3 var jsimp$Coroutine = {
 4     fullname: "jsimp.Coroutine",
 5     baseTypeName: "System.Object",
 6     staticDefinition: {
 7         UpdateMonoBehaviourCoroutine: function (mb){
 8             mb.$UpdateAllCoroutines(UnityEngine.Time.get_deltaTime());
 9         }
10     },
11     assemblyName: "SharpKitProj",
12     Kind: "Class",
13     definition: {
14         ctor: function (){
15             System.Object.ctor.call(this);
16         }
17     }
18 };
19 
20 // replace old Coroutine
21 jsb_ReplaceOrPushJsType(jsimp$Coroutine);

這個文件同樣在 includes.javascript 中進行了包含。

看第8行,調用了 $UpdateAllCoroutines 函數更新協程管理器。

對于 WaitForSeconds 類,C#中并沒有暴露任何接口。我們無法判斷一個 WaitForSeconds 是否時間已到。所以我又自定義了這個類,來達到這個目的。

文件是:StreamingAssets/JavaScript/Manual/UnityEngine_WaitForSeconds.javascript

1 _jstype = undefined;
 2 for (var i = 0; i < JsTypes.length; i++) {
 3     if (JsTypes[i].fullname == "UnityEngine.WaitForSeconds") {
 4         _jstype = JsTypes[i];
 5         break;
 6     }
 7 }
 8 
 9 if (_jstype) {
10 
11     _jstype.definition.ctor = function(a0) { 
12         this.$totalTime = a0;
13         this.$elapsedTime = 0;
14         this.$finished = false;
15     }
16 
17     _jstype.definition.get_finished = function(elapsed) { 
18         if (!this.$finished) {
19             this.$elapsedTime += elapsed;
20             if (this.$elapsedTime >= this.$totalTime) {
21                 this.$finished = true;
22             }        
23         }
24         return this.$finished;
25     }
26 }

這個文件也很簡單,只是記錄初始時的時間,后面更新時時間進行遞增。get_finished() 函數被協程管理器用于判斷時間是否已到。

到此,相信大家對“用C#寫的協程轉換成JavaScript后無法正常工作怎么辦”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

玛沁县| 和龙市| 色达县| 侯马市| 瑞昌市| 安福县| 鹤山市| 聊城市| 建湖县| 本溪| 东兴市| 武乡县| 灵武市| 平潭县| 汉阴县| 周宁县| 武定县| 方正县| 年辖:市辖区| 高唐县| 安塞县| 吉隆县| 馆陶县| 屏南县| 杨浦区| 宁波市| 开原市| 新余市| 吴江市| 任丘市| 阿克陶县| 石林| 新兴县| 遂平县| 阿拉善右旗| 北安市| 山东| 梓潼县| 安远县| 建水县| 杭州市|