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

tsm1rwdh  于 2023-03-19  发布在  Java
关注(0)|答案(3)|浏览(214)

我有一些JavaScript数据,我正在序列化,以便Unity可以将其作为byte[]数组使用,如generally described here。我想通过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长度数组视为返回类型。
问题:
1.正确的做法是什么?
1.如果做不到这一点,至少从JavaScript-to-C的Angular 来看,我做得对吗?C#表示字节数组的方式更有可能出现问题吗?

gudnpqoy

gudnpqoy1#

我希望你找到了解决问题的方法。下面是我的(非常蹩脚的解决方案),但它很有效:

司法支助处

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);
}

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

yebdmbv4

yebdmbv42#

秘诀是要有一个示例化字节数组的方法,然后从js上下文调用它,示例化数组的方法调用js方法,js方法实际填充字节数组,这是一个2步的过程。
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,而使用字符串方法则需要几秒钟。

vfwfrxfs

vfwfrxfs3#

当我希望尽可能少的麻烦时,我使用的一种方法是将数据作为文件保存在emscripten内存文件系统中,然后在C#端读回。尚未测量性能影响,但因为它在内存中,所以理论上性能相当高。
大概是这样的

JSLib

FS.writeFile('/tmp/myfile', data);

注意,FS是一个全局变量,只能从JSLib文件中访问(在Unity中构建时最终为webgl.framework.js)。

C#

var data = File.ReadAllBytes("/tmp/myfile");

相关问题