如何在Unity / C# WebGL平台中调用async/await JavaScript函数?

5

我按照这篇文档在Unity中调用JavaScript函数,以制作WebGL游戏。

但是如果js代码包含async/await,就会出现问题,例如:

C#脚本:

    [DllImport("__Internal")]
    private static extern void Foo();

    [DllImport("__Internal")]
    private static extern void Boo();

    void Start(){
      Foo();
      Boo();
    }

JavaScript mylib.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异步/等待函数?


你正在使用非常老的Unity版本吗?据我所知,Unity不再支持JS,这意味着它可能也不支持ES6+语法... - mcdev
@mcdev 不,我正在使用Unity 2020 LTS。你提到的已弃用的JS支持是关于将JS用作游戏脚本,但我正在为WebGL游戏使用JS,该游戏使用C#作为游戏脚本,并尝试调用网页中的JS脚本。 - CloudL
啊,好的,有点像客户端代码的Web服务调用。 - mcdev
@mcdev Unity从来没有支持JavaScript ;) 你所指的是UnityScript,它只是使用了类似JavaScript的语法,但与C#层类似,基本上只是底层C++引擎的接口。 OP正在询问WebGL,在这里,您可以将应用程序嵌入到HTML页面中,并确实可以与该页面的JavaScript交互;) - derHugo
1个回答

4

简述:这就是如何做到的。在 c# 中不需要了解 async ,它就可以正常工作。


我刚刚使用了一个小测试

Assets/Plugins/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!");
    }
});

and

Assets/Exmaple.cs

public class Example : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void Foo();

    [DllImport("__Internal")]
    private static extern void Boo();

    void Awake()
    {
        Foo();
        Boo();
    }
}

这就是没有任何问题的情况下的样子。

enter image description here

因此,如果没有进一步的信息,我会认为:你的问题不是 async,而是其他原因引起的。


我刚刚尝试了和你一样的代码,但仍然出现错误。我猜测可能是由于Unity版本不同造成的。(我使用的是Unity 2020,而你使用的是2021年版)。 我打算安装Unity 2021,稍后再试一次。 - CloudL
@CloudL 哦,是的...也许他们以前确实不支持它,明天可以再检查一下。 - derHugo
我已经在Unity 2021中尝试了完全相同的代码,它像魔法般地运行! 我查看了Unity 2021.2更新说明,它提到了“将WebGL编译器更新为Emscripten 2.0.19”,所以这可能是关键。 在这个github问题中也提到了异步支持。 总的来说,感谢您的答案,否则我无法自己找出这是Unity版本的问题:D - CloudL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接