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