从C插件向Unity3D发送字节数据的任何正确方法?

这里只是一个好奇的问题。

当您在iOS平台上为Unity编写插件时,插件具有有限的本机到托管回调function(从插件再到Unity)。 基本上这个文档: iOS插件Unity文档

说明你能够回拨的函数签名是这样的:

只能从本机代码调用与以下签名对应的脚本方法:function MethodName(message:string)

C中定义的签名如下所示:

void UnitySendMessage(const char * obj,const char * method,const char * msg);

所以这几乎意味着我只能将字符串发送回Unity。

现在在我的插件中,我使用protobuf-net来序列化对象并将它们发送回Unity以进行反序列化。 我已经让这个工作,但通过一个解决方案我觉得很丑陋,并不是很优雅:

Person* person = [[[[[Person builder] setId:123] setName:@"Bob"] setEmail:@"bob@example.com"] build]; NSData* data = [person data]; NSString *rawTest = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; UnitySendMessage("GameObject", "ReceiveProductRequestResponse", [rawTest cStringUsingEncoding:NSUTF8StringEncoding]); 

基本上我只是将字节流编码为字符串。 在Unity中,我然后获取字符串的字节并从那里反序列化:

 System.Text.UTF8Encoding encoding=new System.Text.UTF8Encoding(); Byte[] bytes = encoding.GetBytes(message); 

这确实有效。 但是真的没有办法做到这一点吗? 也许有人知道如何以某种替代方式完成它?

Base-64(或其他类似的基础)是正确的方法; 你不能在这里使用编码(例如UTF8) – 编码旨在转换:

 arbitrary string <===encoding===> structured bytes 

即字节具有定义的结构; protobuf的情况并非如此; 你想要的是:

 arbitrary bytes <===transform===> structured string 

在大多数情况下,base-64是最方便的实现。 严格来说,你有时可能会高于64,但你可能不得不手动滚动它 – 不漂亮。 Base-64易于理解并得到很好的支持,使其成为一个不错的选择。 我不知道你是怎么用C语言做的,但在Unity中应该只是:

 string s = Convert.ToBase64String(bytes); 

通常,您也可以避免使用额外的缓冲区,假设您在内存中序列化为MemoryStream

 string s; using(var ms = new MemoryStream()) { // not shown: serialization steps s = Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length); } 

基于Marc Gravell答案的示例:

在ios方面:

 -(void)sendData:(NSData*)data { NSString* base64String = [data base64Encoding]; const char* utf8String = [base64String cStringUsingEncoding:NSUTF8StringEncoding]; UnitySendMessage("iOSNativeCommunicationManager", "dataReceived", utf8String); } 

在统一方面:

 public delegate void didReceivedData( byte[] data ); public static event didReceivedData didReceivedDataEvent; public void dataReceived( string bytesString ) { byte[] data = System.Convert.FromBase64String(bytesString); if( didReceivedDataEvent != null ) didReceivedDataEvent(data); }