这里只是一个好奇心的问题。
当您在iOS平台上为Unity编写插件时,插件具有有限的本机到托管回调功能(从插件再到Unity)。 基本上这个文档: iOS插件Unity文档
指出您可以回拨的功能签名是这样的:
只能从本地代码调用与以下签名对应的脚本方法:function MethodName(message:string)
C中定义的签名如下所示:
void UnitySendMessage(const char * obj,const char * method,const char * msg);
所以这意味着我只能将字符串发送回Unity。
现在在我的插件中,我使用protobuf-net来序列化对象并将它们发送回统一进行反序列化。 我已经得到这个工作,但通过我觉得很难看,并且不是很优雅的解决方案:
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);这确实有用。 但是真的没有其他的方式来做这件事吗? 也许有人对如何以其他方式完成这个想法有所了解?
Just a question of curiosity here.
When you write plugins for Unity on the iOS platform, the plugins have a limited native-to-managed callback functionality (from the plugin and then to Unity). Basically this documentation: iOS plugin Unity documentation
states that the function signature you are able to call back to is this:
Only script methods that correspond to the following signature can be called from native code: function MethodName(message:string)
The signature defined in C looks like this:
void UnitySendMessage(const char* obj, const char* method, const char* msg);
So this pretty much means I can only send strings back to Unity.
Now in my plugin I'm using protobuf-net to serialize objects and send them back to unity to be deserialized. I have gotten this to work, but by a solution I feel is quite ugly and not very elegant at all:
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]);Basically I simply encode the bytestream into a string. In Unity I then get the bytes of the string and deserialize from there:
System.Text.UTF8Encoding encoding=new System.Text.UTF8Encoding(); Byte[] bytes = encoding.GetBytes(message);This does work. But is there really no other way of doing it? Perhaps someone have an idea of how it could be done in some alternative way?
最满意答案
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); }Base-64 (or another similar base) is the correct way to do this; you cannot use an encoding here (such as UTF8) - an encoding is intended to transform:
arbitrary string <===encoding===> structured bytesi.e. where the bytes have a defined structure; this is not the case with protobuf; what you want is:
arbitrary bytes <===transform===> structured stringand base-64 is the most convenient implementation of that in most cases. Strictly speaking, you can sometimes go a bit higher than 64, but you'd probably have to roll it manually - not pretty. Base-64 is well-understood and well-supported, making it a good choice. I don't know how you do that in C, but in Unity it should be just:
string s = Convert.ToBase64String(bytes);Often, you can also avoid an extra buffer here, assuming you are serializing in-memory to a MemoryStream:
string s; using(var ms = new MemoryStream()) { // not shown: serialization steps s = Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length); }更多推荐
发布评论