简体   繁体   English

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

[英]Any proper way of sending byte data to Unity3D from a C plugin?

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). 当您在iOS平台上为Unity编写插件时,插件具有有限的本机到托管回调功能(从插件再到Unity)。 Basically this documentation: iOS plugin Unity documentation 基本上这个文档: iOS插件Unity文档

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) 只能从本机代码调用与以下签名对应的脚本方法:function MethodName(message:string)

The signature defined in C looks like this: C中定义的签名如下所示:

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

So this pretty much means I can only send strings back to Unity. 所以这几乎意味着我只能将字符串发送回Unity。

Now in my plugin I'm using protobuf-net to serialize objects and send them back to unity to be deserialized. 现在在我的插件中,我使用protobuf-net来序列化对象并将它们发送回Unity以进行反序列化。 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: 在Unity中,我然后获取字符串的字节并从那里反序列化:

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 (or another similar base) is the correct way to do this; Base-64(或其他类似的基础)是正确的方法; you cannot use an encoding here (such as UTF8) - an encoding is intended to transform: 不能在这里使用编码(例如UTF8) - 编码旨在转换:

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

ie where the bytes have a defined structure; 即字节具有定义的结构; this is not the case with protobuf; protobuf的情况并非如此; what you want is: 你想要的是:

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

and base-64 is the most convenient implementation of that in most cases. 在大多数情况下,base-64是最方便的实现。 Strictly speaking, you can sometimes go a bit higher than 64, but you'd probably have to roll it manually - not pretty. 严格地说,你有时可能会高于64,但你可能不得不手动滚动它 - 不漂亮。 Base-64 is well-understood and well-supported, making it a good choice. Base-64易于理解并得到很好的支持,使其成为一个不错的选择。 I don't know how you do that in C, but in Unity it should be just: 我不知道你是怎么用C语言做的,但在Unity中应该只是:

string s = Convert.ToBase64String(bytes);

Often, you can also avoid an extra buffer here, assuming you are serializing in-memory to a MemoryStream : 通常,您也可以避免使用额外的缓冲区,假设您在内存中序列化为MemoryStream

string s;
using(var ms = new MemoryStream()) {
    // not shown: serialization steps

    s = Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}

Example based on Marc Gravell's answer: 基于Marc Gravell答案的例子:

On the ios side: 在ios方面:

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

and on the unity side: 在统一方面:

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

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

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