如何在 Unity/C# WebGL 平台中调用 async/await JavaScript 函数?
Posted
技术标签:
【中文标题】如何在 Unity/C# WebGL 平台中调用 async/await JavaScript 函数?【英文标题】:How to call async/await JavaScript function in Unity/C# WebGL platform? 【发布时间】:2021-12-23 16:25:36 【问题描述】:我跟着 this doc 在 Unity 中从我的 C# 脚本调用 javascript 函数来制作 WebGL 游戏。
但是如果js代码中包含async/await就有问题了,例如:
C# 脚本:
[DllImport("__Internal")]
private static extern void Foo();
[DllImport("__Internal")]
private static extern void Boo();
void Start()
Foo();
Boo();
JavaScriptmylib.jslib
mergeInto(LibraryManager.library,
// works well
Foo: function ()
window.alert("Hello, world!");
,
// error: can't compile
Boo: async function ()
var s = function (ms)
return new Promise(resolve => setTimeout(resolve, ms));
;
await s(2000);
window.alert("Boo!");
);
当我尝试构建这些代码时,它显示如下错误:
Failed process stderr log:
error: failure to execute js library "D:\CloudLinProject\Unity\My project\Assets\Plugins\Javascripts\PhantomAPI.jslib": SyntaxError: Unexpected token function,,SyntaxError: Unexpected token function
at Object.load (eval at globalEval (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:105:8), <anonymous>:179:14)
at JSify (eval at globalEval (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:105:8), <anonymous>:87:20)
at D:\CloudLinProject\Unity\My project\Assets\Plugins\Javascripts\PhantomAPI.jslib (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:221:3)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)
preprocessed source (you can run a js engine on this to get a clearer error message sometimes):
Internal compiler error in src/compiler.js! Please raise a bug report at https://github.com/kripken/emscripten/issues/ with a log of the build and the input files used to run. Exception message: "SyntaxError: Unexpected token function" | SyntaxError: Unexpected token function
at Object.load (eval at globalEval (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:105:8), <anonymous>:179:14)
at JSify (eval at globalEval (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:105:8), <anonymous>:87:20)
at Object.<anonymous> (D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\src\compiler.js:221:3)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)
Traceback (most recent call last):
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emcc.py", line 3063, in <module>
sys.exit(run())
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emcc.py", line 1780, in run
final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\tools\shared.py", line 2274, in emscripten
emscripten._main(cmdline)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 2233, in _main
return temp_files.run_and_clean(lambda: main(
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\tools\tempfiles.py", line 93, in run_and_clean
return func()
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 2238, in <lambda>
DEBUG=DEBUG,
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 2164, in main
temp_files=temp_files, DEBUG=DEBUG)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 86, in emscript
glue, forwarded_data = compiler_glue(metadata, libraries, compiler_engine, temp_files, DEBUG)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 218, in compiler_glue
glue, forwarded_data = compile_settings(compiler_engine, libraries, temp_files)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten.py", line 541, in compile_settings
cwd=path_from_root('src'), error_limit=300)
File "D:\Program Files\Unity\2020.3.22f1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\tools\jsrun.py", line 132, in run_js
raise Exception('Expected the command ' + str(command) + ' to finish with return code ' + str(assert_returncode) + ', but it returned with code ' + str(proc.returncode) + ' instead! Output: ' + str(ret)[:error_limit])
Exception: Expected the command ['D:/Program Files/Unity/2020.3.22f1/Editor/Data\\Tools\\nodejs\\node.exe', '--stack_size=8192', '--max-old-space-size=4096', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\Emscripten\\src\\compiler.js', 'C:\\Users\\eucyl\\AppData\\Local\\Temp\\tmpoqhbko.txt', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Audio.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\case_1174367_workaround.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\case_1179945_workaround.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\case_1187965_workaround.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\case_1208971_workaround.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Cursor.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Eval.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\FileSystem.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Logging.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Profiler.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\SystemInfo.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\UnetWebSocket.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\Video.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\WebCam.js', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\lib\\WebRequest.js', 'D:\\CloudLinProject\\Unity\\My project\\Assets\\Plugins\\Javascripts\\PhantomAPI.jslib', 'D:\\Program Files\\Unity\\2020.3.22f1\\Editor\\Data\\PlaybackEngines\\WebGLSupport\\BuildTools\\Emscripten\\src\\library_pthread_stub.js'] to finish with return code 0, but it returned with code 1 instead! Output: // The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) ..generated code..
// 3. pre-run appended it, var Module = ; ..generated
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
那么我应该如何处理 C# 中的 js async/await 函数呢?
【问题讨论】:
您使用的是非常旧的 Unity 版本吗?据我所知 Unity 不再支持 JS,这意味着它也可能不支持 ES6+ 语法 ... @mcdev 不,我使用的是 Unity 2020 LTS。你提到的不推荐使用的 JS 支持是关于使用 JS 作为游戏脚本,但我正在使用 JS 进行 WebGL 游戏,它使用 C# 作为游戏脚本并尝试调用网页中的 JS 脚本。 啊,好吧,有点像 web 服务调用,但用于客户端代码 @mcdev Unity never 根本不支持 JavaScript ;) 你指的是 UnityScript 并且只使用了类似于 JavaScript 的语法,但是类似于 c# 层,基本上只是底层 C++ 引擎的接口。 OP 询问WebGL,您基本上在哪里托管嵌入在 html 页面中的应用程序,然后确实可以与该页面的 JavaScript 进行交互;) 【参考方案1】:tl;dr:就是这样。 c#
不需要知道async
,它应该可以工作。
我刚刚做了一个小测试
资产/插件/mylib.jslib
mergeInto(LibraryManager.library,
Foo: function ()
window.alert("Foo!");
,
Boo: async function ()
var s = function (ms)
return new Promise(resolve => setTimeout(resolve, ms));
;
await s(2000);
window.alert("Boo!");
);
和
资产/Exmaple.cs
public class Example : MonoBehaviour
[DllImport("__Internal")]
private static extern void Foo();
[DllImport("__Internal")]
private static extern void Boo();
void Awake()
Foo();
Boo();
这是没有任何问题的样子
因此,如果没有更多信息,我会声称:您发出的不是async
,而是其他东西。
【讨论】:
我刚刚尝试了与您相同的代码,但仍然出现错误。我猜这可能是由 Unity 版本差异引起的。 (我使用的是 Unity 2020,而您使用的是 2021 年)。我将安装 Unity 2021,稍后再试。 @CloudL 哦,是的 .. 也许他们实际上不支持它,明天再检查一下 我已经在 Unity 2021 中尝试过使用完全相同的代码,而且效果非常棒!我查看了Unity 2021.2 update notes,它提到了“将 WebGL 编译器更新为 Emscripten 2.0.19”,因此它可能是关键。在这个github issue 中也提到了异步支持。总的来说,感谢您的回答,否则我自己无法弄清楚这是 Unity 版本的问题:D以上是关于如何在 Unity/C# WebGL 平台中调用 async/await JavaScript 函数?的主要内容,如果未能解决你的问题,请参考以下文章