Warning
Warning: Unity Simulation is deprecated as of December 2023, and is no longer available.
Synchronize custom data between the Server and Clients
By default, Distributed Rendering only synchronizes GameObject transforms between the Server and Clients. Your specific use case might require you to synchronize other types of data as well. For example, if your robot attempts to pick and place objects that change colour, you may want to synchronize the object colour across Clients. This section explains how you can do this by sending this colour information to the Client as custom data.
Sending custom data can be especially useful for synchronizing material properties, text based statistics, particle effects like weather or clouds, and compute shader based results. The ISerializationProxy interface in Distributed Rendering enables users to send custom data from the Server to the Clients, by implementing the WriteCustom and ReadAndApply methods. These functions must internally use the Write and Read implementations provided in the package, which contain various overrides for different data types.
Usage
WriteCustom
In this function, we use the serializer.Write() function to write data from the Server. serializer.Write() can be used to write int, long, UInt32, float, bool, string, Vector3, Transform, Quaternion, TransformProxy, NetworkMessageType and CommandType data types.
To send data, pass it to the function in the following manner:
public void WriteCustom(IMessageWriter serializer)
{
var writeData = "We are sending this data to render nodes!";
serializer.Write(writeData);
}
ReadAndApply
In this function, we use the varying types of serializer.Read() function to read data sent by the Server. Unlike serializer.Write(), this function has specific functions for each data type and cannot be implicitly overwritten. For example, the function to read int data is ReadInt(), for float is ReadFloat() etc.
To read data, read from the function in the following manner:
public void ReadAndApply(IMessageReader serializer)
{
var readData = serializer.ReadString();
UIText.text = readData;
}
Here we are passing it to a text object on the UI Canvas so that it can be displayed on the Clients.
Note: Make sure the reads and writes are in order!
Synchronize Custom Data: Material properties
One form of custom data that can be sent to Clients is material properties like RGB values. To implement this, with Distributed Rendering, we have set up a scene in Unity that contains a cube with one material attached to it (named cubeMaterial in the recipe below), and one camera that completes revolutions around it. We have then attached the following script to the cube object to synchronize RGB data between the Server and Client.
using System.Collections;
using System.Collections.Generic;
using Unity.Simulation.DistributedRendering.Core;
using UnityEngine;
using UnityEngine.UI;
public class ISerializationProxyColor : MonoBehaviour, ISerializationProxy
{
public Material cubeMaterial;
public Text RGBText;
public void WriteCustom(IMessageSerializer serializer)
{
// For cube color
Vector3 writeColor = (Vector4)cubeMaterial.color;
serializer.Write(writeColor);
}
public void ReadAndApply(IMessageSerializer serializer)
{
// For cube color
Vector3 readColor = serializer.ReadVec3();
cubeMaterial.color = new Color(readColor.x, readColor.y, readColor.z, 1);
// UI RGB display
RGBText.text = "R: " + cubeMaterial.color.r*255f + "\n"
+ "G: " + cubeMaterial.color.g*255f + "\n"
+ "B: " + cubeMaterial.color.b*255f + "\n";
}
}
Let us further break this script down.
To start synchronizing your data, the first step is to add a using directive for the Unity.Simulation.DistributedRendering.Core namespace in order to access the APIs. Once done, make sure to inherit the ISerializationProxy interface, which enforces that WriteCustom and ReadAndApply are implemented.
Next, implement the WriteCustom and ReadAndApply methods. WriteCustom is used to send the material color to the Clients. Since the serializer.Write function in distributed rendering does not accept Vector4 or Color types, we convert the cubeMaterial RGBA data to a Vector3, and then send it using serializer.Write.
Correspondingly implement ReadAndApply, which is where the Clients read the incoming custom data. Here we read the Vector3 data that the Server sent using serializer.ReadVec3(), and then manually set the cubeMaterial RGBA values.
In this example we additionally display the data we read on the Client UI, so that we can quantify the visual changes.
Building this scene and then launching it gives us the following output on the Client:

A detailed tutorial for this can be found in this demo repository.
Synchronize Custom Data: VFX and Compute Shaders
While particle effects and compute shaders don't have explicit custom data that needs to be synced for them to function correctly, the way they are called must be explicitly synced between the Server and Clients for better simulation integrity.
The process to synchronize the way they are called is very similar to synchronizing custom data, except in this case instead of sending and receiving data trigger functions are called.
public void WriteCustom(IMessageSerializer serializer)
{
// Play effect or trigger shader dispatch code
}
public void ReadAndApply(IMessageSerializer serializer)
{
// Play effect or trigger shader dispatch code
}

A detailed tutorial for synchronized compute shaders can be found in this demo.

A detailed tutorial for synchronized particle systems can be found in this demo.