SERIALIZATION AND DATA TYPES

SERIALIZATION AND DATA TYPES

uLink will automatically serialize the data sent to other nodes in the network. This process works in the same way for both state synchronization and RPCs. If you want to customize the serialization algorithms or add support for more data types, this can be achieved by writing your own codecs and adding them to uLink.

Supported data types

The following data types are supported in uLink serialization.
  1. Built-in data types in .NET.
    (http://msdn.microsoft.com/en-us/library/cs7y5x0x(VS.90).aspx)
  2. Arrays of built-in data types.
  3. If the data type is nullable it is also supported.
  4. The following uLink classes: NetworkPlayer, NetworkViewID, NetworkPeer.
  5. The following Unity classes: Vector2, Vector3, Vector4, Quaternion, Color.
  6. Enums
  7. Any user defined class where all members have types described in this enumerated list. This works recursively in a hierarchy of classes as long as all members are ultimately defined in this list.

User-defined codecs

uLink lets you define your own serialization codecs for any data type you wish. Sometimes it is desirable to tweak the serialization algorithms for certain data types. For example, you might want to save bandwidth and transfer certain data at a lower accuracy. Another scenario is when you want to serialize a data type not included in the built-in types listed above.
Writing and registering your own codec is simple. First you need to implement two methods, one for serialization that conforms to the uLink.BitStreamCodec.Serializer delegate, and one for deserialization that conforms to the uLink.BitStreamCodec.Deserializer delegate. These methods can have any name you wish, as long as the parameter numbers and type match the delegate definitions.
The remaining step is to register your codec with uLink. This is done by using the uLink.BitStreamCodec.Add() method, where you give the implemented serializer and deserializer methods as parameters.
Choose one of these methods based on whether you need null-value or array support. The method must be called on both server and client. Note that the nullable feature only works with structures.

Example

Say you have a data type in your game that is represented by three float values. However only one of these values needs to be synchronized across the network. Below, this is implemented by writing a custom codec for the class.
using uLink; using UnityEngine; using uLobby;
public class CodecExample : uLink.MonoBehaviour { // The class we want to be able to serialize. class MyClass { // This value should be part of the serialization. private float a; // These values should not be part of the serialization. private float b, c;
// Method conforming to the Serializer delegate. public static void WriteMyClass(uLink.BitStream stream, object value, params object[] codecOptions) { MyClass myObj = (MyClass) value; stream.Write<float>(myObj.a); }
// Method conforming to the Deserializer delegate. public static object ReadMyClass(uLink.BitStream stream, params object[] codecOptions) { MyClass myObj = new MyClass(); myObj.a = stream.Read<float>(); return myObj; } }
void Awake() { // This method call must be made on both the client and the server. uLink.BitStreamCodec.Add<MyClass>(MyClass.ReadMyClass, MyClass.WriteMyClass); } }

Arrays of custom types and nullable custom types

If you want you new type serialization to handle arrays of objects of that type you can use the uLink.BitStreamCodec.AddAndMakeArray() method to register the type codec. This replaces the call to uLink.BitStreamCodec.Add(). Further, if you want the serialized type to be nullable as well, i.e. that you should be able to give null for the object reference when serializing it, you can use the uLink.BitStreamCodec.AddAndMakeNullableAndArray() method.

Type safety

When you define an RPC and make a call to it over the network, uLink does all the magic of data serialization for you. The call practically works just like a good old method call between two regular classes. But under the surface there are some dangers lurking. Take the following RPC, defined in a C# script, for example.
[RPC] public void ApplyDamage(long damage) { this.damage += damage; }
Let's say someone is writing a client that calls this RPC, and does the following.
float damage = 2.0f; networkView.RPC("ApplyDamage", damage);
The RPC was defined as having an integer parameter, but we called it using a float. The value will be a garbage value when arriving to the server. Situations like can cause subtle bugs which can be notoriously hard to track down.
To help with this problem, uLink has a type safe serialization mode that can catch these problems at runtime, and throw an appropriate exception when there is a mismatch between the data type being sent and what the receiver expects.
The type code is serialized together with the data when type safety is turned on. You can supply a type code for a new type after the serializer and deserializer methods in the uLink.BitStreamCodec.Add() call.
This feature is enabled for any project running inside the Unity editor, so you can catch these errors during development and testing. It is however turned off when running a project as a stand-alone executable or in the web player. Type safety adds extra data to each network call, and it is therefore not recommended to use it in production systems, for bandwidth purposes.
If you wish to turn type safety on anyway, set the uLink.Network.isTypeSafeByDefault property to true.
To enable type safety for a specific RPC call, set the NetworkFlag TypeUnsafe to 0. The following code accomplishes this.
networkView.RPC(uLink.NetworkFlags.Normal - uLink.NetworkFlags.Unbuffered, "ApplyDamage", damage);
Note that type safety can currently only be enabled for RPCs, not for state synchronization.