Any correct way to send byte data to Unity3D from C plugin?

Just a matter of curiosity here.

When you write plugins for Unity on the iOS platform, plugins have limited callback functionality with controlled handling (from the plugin and then to Unity). Basically this documentation: iOS plugin Unity documentation

indicates that the signature of the function you can call back is as follows:

Only script methods that match 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 that I can only send strings to Unity.

Now in my plugin I use protobuf-net to serialize objects and send them back to the unit for deserialization. I got this to work, but the solution I feel is pretty ugly and not very elegant:

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 just encode the byte stream to a string. In Unity, I get the bytes of the string and deserialize from there:

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

It works. But is there no other way to do this? Perhaps someone has an idea of ​​how this can be done in some other way?

+7
source share
2 answers

Base-64 (or another similar base) is the right way to do this; you cannot use the encoding here (for example, UTF8) - the encoding is intended to be converted:

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

i.e. where bytes have a specific structure; this does not apply to protobuf; What would you like:

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

and base-64 is the most convenient implementation of this in most cases. Strictly speaking, sometimes you can go a little higher than 64, but you probably have to roll manually - not really. Base-64 is well understood and well supported, making it a good choice. I don't know how you do it in C, but in Unity it should be simple:

 string s = Convert.ToBase64String(bytes); 

Often you can also avoid using an extra buffer by assuming that you are serializing in memory in a MemoryStream :

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

An example based on the answer of Mark Gravell:

On the ios side:

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

and on the side of unity:

 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); } 
+2
source

All Articles