Author Topic: RFC Parameters  (Read 10505 times)

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
RFC Parameters
« on: March 07, 2014, 04:49:09 AM »
Hi forum, I gather by what I've read here that remote function calls only support individual, primitive type parameters? I've not been able to find "proper" api documentation to confirm this. In my simple test I have a very simple class containing only primitive types, when passed as a parameter it throws an exception. Before I go and add this functionality, is it throwing because I have missed something or is there a particular reason why this is not allowed/implemented? (I appreciate there are limiting factors concerning binary conversion of complex collections such as list and dictionaries).

Note. I know I can do this with custom custom packet handlers but I'd prefer from an OO design point of view that this was abstracted away with an RFC.

I like the package so far. I'd be nice to have some more complete documentation (or more obvious links to it) though. Cheers.

Of course if I missed both the above then I'll  :-X and sorry for wasting your time!

Edit: sounded like I was bitching
« Last Edit: March 07, 2014, 05:37:23 AM by o0Raven0o »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #1 on: March 07, 2014, 11:07:50 AM »
TNet.UnityTools.CanBeSerialized function has a list of all the data types you can send via RFC parameters:
  1.                 if (type == typeof(bool)) return true;
  2.                 if (type == typeof(byte)) return true;
  3.                 if (type == typeof(ushort)) return true;
  4.                 if (type == typeof(int)) return true;
  5.                 if (type == typeof(uint)) return true;
  6.                 if (type == typeof(float)) return true;
  7.                 if (type == typeof(string)) return true;
  8.                 if (type == typeof(Vector2)) return true;
  9.                 if (type == typeof(Vector3)) return true;
  10.                 if (type == typeof(Vector4)) return true;
  11.                 if (type == typeof(Quaternion)) return true;
  12.                 if (type == typeof(Color32)) return true;
  13.                 if (type == typeof(Color)) return true;
  14.                 if (type == typeof(DateTime)) return true;
  15.                 if (type == typeof(IPEndPoint)) return true;
  16.                 if (type == typeof(bool[])) return true;
  17.                 if (type == typeof(byte[])) return true;
  18.                 if (type == typeof(ushort[])) return true;
  19.                 if (type == typeof(int[])) return true;
  20.                 if (type == typeof(uint[])) return true;
  21.                 if (type == typeof(float[])) return true;
  22.                 if (type == typeof(string[])) return true;
These types are serialized in TNet.UnityTools.WriteObject and ReadObject. If you want to add your own custom types, you certainly can -- just be aware that all 3 functions will need to be modified.

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: RFC Parameters
« Reply #2 on: March 07, 2014, 12:26:10 PM »
Hi Aren thanks for the reply. I've looked at the code you mentioned, forgive me for saying so but it's pretty ugly! Must be a nightmare to maintain. I'll not get in to programming best practices here but that's a heck of a lot of duplicated code. Is that for some sort of cross platform / Unity / performance reason? Speaking purely MS C# there is certainly more than one way you could improve it, not just performance wise but also from a maintainability and extensibility point of view.

I kind of feel like you are reinventing the wheel a little bit on your usage of BinaryWriter too? Would it not have been easier to you use BinaryFormatter? I'm not especially familiar with Unity's .Net IL parser but I don't see any major issues performance and compatibility wise, it would save you a lot of time writing out the fields and properties of complex objects. You could mostly retire those mammoth if else blocks too.

Thanks for pointing me in the right direction though, I appreciate the swift response. I guess I'll make a few changes but I see where you are going with things.

Cheers.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #3 on: March 08, 2014, 01:46:59 PM »
BinaryFormatter is great if you know what to expect. If you know that you will always get struct A followed by int B followed by Vector3 C -- it's all fine. My class makes it possible to have variable data in there, which is a must to have with RFCs that can have various parameters. Maybe there is a way to do this with the BinaryFormatter as well? If so, I just don't know it well enough.

In any case, in my system when parsing the packet's data, first comes the type identifier, followed by an arbitrary amount of data for this type. The identifier tells me what kind of data it is, which lets me read it properly in its native form. Once I have all the data from a packet, I now know what the RFC function should look like, allowing me to call it. And all of this is done without any extra memory allocation, working with the same continuous stream that can have more than one packet inside of it.

As an added benefit, using my own custom serialization allows me to create a C++ version of the server, which will perform even better.

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: RFC Parameters
« Reply #4 on: March 10, 2014, 06:07:39 AM »
Fair point I can see how that is an advantage, especially when performance is concerned.

"If you know that you will always get struct A followed by int B followed by Vector3 C -- it's all fine." This btw, doesn't matter as the BinaryFormatter class figures it all out for you returning a boxed object.

I guess something I also have to consider is that if I update the TNet.UnityTools class to serialize / deserialize my own objects then its no longer going to work with the standalone server? This'd be a problem for me in the future as I'll most likely want to use it on an Azure box.

Anyway, here is what I did to get TNet to work will all data types (excluding some collection types). First off I identified any types that weren't supported in Aren's list. I then created a new "tnet type" and serialized the unsupported type (using the BinaryFormatter classes) sending it as a byte array. I then detected my new "tnet type" on read and deserialized the bytes using BinaryFormatter again. This returns a simple boxed object type that could be passed through Aren's normal RFC invocation code (with a few tweaks). Job done :)

Couple of points for others who may want to do this, a. it has additional overheads and b. you should consider why you are sending so much data in the first place. It is convenient though not "free". As mentioned above this won't work with the native server app as it won't know what to do with the new "tnet type" (correct me if I am wrong here Aren).

Edit:

Where I have wanted to use the native TNet server I have instead created some helper classes to shift the concerns of binary serialization out of Aren's base classes to my Unity application. It just deals with sending and receiving primitive byte arrays across the TNet infrastructure instead, thus maintaining server compatibility.

Aren, I'm happy to talk more about this if it's something that interests you.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #5 on: March 10, 2014, 09:45:56 PM »
That's a nice approach.

Currently the type serialization is all done on the client side. It's not used on the server side at all. Server side passes RFC data as-is. It would be necessary on the server if you were doing any kind of validation / checking / anti-hacking logic though.

Be careful with the BinaryFormatter usage... Garbage Collection hiccups on Unity are the devil, and frequent packets that make use of the Binary Formatter will result in just that.

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: RFC Parameters
« Reply #6 on: March 11, 2014, 04:58:54 AM »
Thanks for your replies Aren, I appreciate you making the effort to respond.

Cheers for the heads up on GC. I'm only using the BinaryFormatter method to sync initial game state (game options etc.), so it's being used very sparingly. Do you (or any other kind user), have any resources you could link me on the nature of Unity garbage collection procedures? I already found this:

https://docs.unity3d.com/Documentation/Manual/UnderstandingAutomaticMemoryManagement.html

But I imagine it doesn't tell the whole story. I'm familiar with the MS .Net process so technical resources aren't a problem.

Thanks also for letting me know about the server code too. I am yet to look at it so it's good to know a lot of what I've done already will work out of the box.

Edit:

Found some more info on Unity C# GC.

http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php
http://www.gamasutra.com/blogs/WendelinReich/20131119/203842/C_Memory_Management_for_Unity_Developers_part_2_of_3.php
http://www.gamasutra.com/blogs/WendelinReich/20131127/203843/C_Memory_Management_for_Unity_Developers_part_3_of_3.php
« Last Edit: March 11, 2014, 05:11:21 AM by o0Raven0o »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #7 on: March 11, 2014, 08:01:09 PM »
Unity uses Mono, not .NET. NET GC is much better than the old version of Mono used by Unity. You pretty much need to shoot for 0 frame-to-frame memory allocations with Unity at run-time.

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: RFC Parameters
« Reply #8 on: March 12, 2014, 05:40:29 AM »
Yeah I appreciate that but Mono is an open source implementation of .Net architecture, so I wanted to know how it differs from the MS implementation. The fact that it (the version that unity is using), uses a Boehm garbage collector is the root of it's problems, it's too slow to collect and certainly doesn't do it in a smart way, very much old technology. Hopefully the Unity dev team will upgrade to a newer version of mono soon as it seems the latest versions have gone a long way to address this issue. See here:

http://www.mono-project.com/Generational_GC

With any luck it'll happen faster than the new UI they've been promising (hows that going btw?  ;)).

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #9 on: March 13, 2014, 12:36:28 AM »
I left Unity at the end of November last year, so I wouldn't be able to tell you. I'll say this though... Mono may be open source, but it can be very expensive when someone actually wants to use it in a closed source project.

o0Raven0o

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: RFC Parameters
« Reply #10 on: March 14, 2014, 09:01:44 AM »
Ah, sorry didn't know that! Moving on to pastures greener I hope.  8)

Mono may be open source, but it can be very expensive when someone actually wants to use it in a closed source project.

Fair point I hadn't considered that. Still the GC does choke a lot of serious commercial games (how much does Kerbal stutter with it!!!), so I hope they upgrade soon.

Going back on topic, if anyone wants my code for serializing objects outside of the standard list that TNet supports (and assuming Aren doesn't mind), please let me know. It's less than 20 lines of code, but it's provided as is so don't blame me/Aren if it breaks or slows down your game.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: RFC Parameters
« Reply #11 on: March 14, 2014, 12:45:54 PM »
As long as you don't share TNet's code in its entirety, you are welcome to share the modified files.

And yes, KSP's GC spikes are brutal and have cost many kerbals their very lives. I would know. 225 hours /played in that game. :|