Data types
The client and server can pass data to each other via Remote Actions, State Synchronization or via Network Messages
Mirror supports a number of data types you can use with these, including:
Basic C# types (byte, short, int, long, uint, ushort, ulong, float, double, char, string, etc.)
Built-in Unity math types (Vector3, Quaternion, Rect, Plane, etc.)
Built-in Unity types that are structs under the hood (Color, Sprite, Texture2D, Ray, etc.)
URI
NetworkIdentity
,NetworkBehaviour
These should not be used in SyncVars or Sync* Collections or Rpc's because they'll be null on the client if the corresponding object hasn't already been spawned.
Game object with a
NetworkIdentity
component that have been network spawnedNot prefabs!
See important details in GameObjects section below.
Structures with any of the above
You must replace the whole struct value, not just change its properties
It's recommended to implement IEquatable to avoid boxing, and to have the struct readonly because modifying one of properties does not cause a resync
Classes as long as each field has a supported data type
You must replace the whole class value, not just change its properties
These will allocate garbage and will be instantiated new on the receiver every time they're sent.
ScriptableObject as long as each field has a supported data type
These will allocate garbage and will be instantiated new on the receiver every time they're sent.
See details in the ScriptableObjects section below.
Arrays of any of the above
Not supported with Sync* collections
ArraySegments of any of the above
Not supported with Sync* collections
Game Objects
Game Objects in SyncVars, SyncLists, and SyncDictionaries are fragile in some cases, and should be used with caution.
As long as the game object already exists on both the server and the client, the reference should be fine.
When the sync data arrives at the client, the referenced game object may not yet exist on that client, resulting in null values in the sync data. This is because internally Mirror passes the netId
from the NetworkIdentity
and tries to look it up on the client's NetworClient.spawned
dictionary.
If the object hasn't been spawned on the client yet, no match will be found. It could be in the same payload, especially for joining clients, but after the sync data from another object.
It could also be null because the game object is excluded from a client due to network visibility, e.g. Interest Management
.
You may find that it's more robust to sync the NetworkIdentity.netID
(uint) instead and do your own lookup in NetworkClient.spawned
to get the object, perhaps in a coroutine:
Custom Data Types
Sometimes you don't want mirror to generate serialization for your own types. For example, instead of serializing quest data, you may want to serialize just the quest id, and the receiver can look up the quest details by the id in a predefined list or database.
Sometimes you may want to serialize data which uses a different type not supported by Mirror, such as DateTime.
You can add support for any type by adding extension methods to NetworkWriter
and NetworkReader
. For example, to add support for DateTime
, add this somewhere in your project:
...then you can use DateTime
in your [Command]
or SyncList
Inheritance and Polymorphism
Sometimes you might want to send a polymorphic data type to your commands. Mirror does not serialize the type name to keep messages small and for security reasons, therefore Mirror cannot figure out the type of object it received by looking at the message.
This code does not work out of the box.
CmdEquip will work if you provide a custom serializer for the Item
type. For example:
ScriptableObjects
People often want to send scriptable objects from the client or server. For example, you may have a bunch of swords created as scriptable objects and you want put the equipped sword in a syncvar. This will work fine, Mirror will generate a reader and writer for scriptable objects by calling ScriptableObject.CreateInstance and copy all the data.
However the generated reader and writer are not suitable for every occasion. Scriptable objects often reference other assets such as textures, prefabs, or other types that can't be serialized. Scriptable objects are often saved in the in the Resources folder. Scriptable objects sometimes have a large amount of data in them. The generated reader and writers may not work or may be inneficient for these situations.
Instead of passing the scriptable object data, you can pass the name and the other side can lookup the same object by name. This way you can have any kind of data in your scriptable object. You can do that by providing a custom reader and writer. Here is an example:
Last updated