繁体   English   中英

将字节数组从 JavaScript 返回到 Emscripten/Unity Web 程序集

[英]Returning a byte array from JavaScript to Emscripten/Unity Web Assembly

我有一些 JavaScript 数据,我正在对其进行序列化,以便 Unity 可以将其作为 byte[] 数组使用,如此处一般所述 我想通过这样的 jslib 接口将这些数据公开给 Unity:

[DllImport("__Internal")]
private static extern byte[] GetByteArray();

我尝试使用 emscripten 中的内置方法从 JavaScript 桥接我的值:

  GetByteArray: function () {
    var myTypedArray = new Uint8Array([10, 20, 30, 40, 50]);
    var buf = _malloc(myTypedArray.length * myTypedArray.BYTES_PER_ELEMENT);
    writeArrayToMemory(myTypedArray, buf);
    return buf;
  },

不幸的是,这不起作用——webassembly C# 只将 0 长度数组视为返回类型。 我还尝试HEAPU8.set(myTypedArray, buf)类的东西。

问题:

  1. 这样做的正确方法是什么?
  2. 如果做不到这一点,我是否至少从 JavaScript-to-C 的角度正确地做到了这一点? C# 表示字节 arrays 的方式更有可能出现问题吗?

我希望你找到了解决你的问题的方法。 这是我的(非常hacky的解决方案),但它有效:

jslib

GetByteArray: function(){
    var array = new Uint8Array([10, 20, 30, 40, 50]);
    var str = array.toString();
    str = '[' + str + ']';
    unityInstance.sendMessage('gameObject', 'ByteArrayAvailable', str);
}

C#

#if UNITY_WEBGL && !UNITY_EDITOR

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

#endif

...
    
void CallWebGL()
{
    GetByteArray();
}

void ByteArrayAvailable(string byteArrayStr)
{
    var byteArray = JsonConvert.DeserializeObject<byte[]>(byteArrayStr);
}

您需要将 Newtonsoft.Json.dll 添加到您的插件文件夹中以使其工作,但这是我发现使其工作的唯一简单方法:)

秘诀是有一个方法来实例化字节数组并从 js 上下文中调用它。 实例化数组的方法然后调用实际填充字节数组的js方法。 这是一个两步过程。

C# 边

[DllImport("__Internal", EntryPoint = "getByteArrayTmp")]
private static extern void getByteArrayTmp(Action<int> instantiateByteArrayCallback);
[DllImport("__Internal", EntryPoint = "getByteArray")]
private static extern void getByteArray(Action callback, byte[] byteArray);
 
private static event Action callbackEvent;
 
public static byte[] byteArray;
 
[MonoPInvokeCallback(typeof(Action))]
private static void callback() {
    callbackEvent?.Invoke();
    callbackEvent = null;
}
 
[MonoPInvokeCallback(typeof(Action<int>))]
private static void instantiateByteArrayCallback(int size) {
    byteArray = new byte[size];
    getByteArray(callback, byteArray);
}

用户实际调用的方法是

public static void getByteArray(Action callback) {
    #if UNITY_WEBGL && !UNITY_EDITOR
        callbackEvent = null;
        callbackEvent += callback;
        getByteArrayTmp(instantiateByteArrayCallback);
    #endif
}

在 js 方面

getByteArrayTmp: function(instantiateByteArrayCallback) {
    const byteArray = new Uint8Array([21, 31]);//example
    Module["yourplugin"].byteArray = byteArray;
    Module.dynCall_vi(instantiateByteArrayCallback, byteArray.length);
     
},
getByteArray: function(callback, byteArray) {
    Module.HEAPU8.set(Module["yourplugin"].byteArray, byteArray);
    Module.dynCall_v(callback);
},

这比使用字符串作为中间体要快几倍。 您可以像这样在不到一秒的时间内将超过 20MB 的数据从 js 传输到 Unity,而使用字符串方法则需要几秒钟。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM