Unity
Simulate includes an integration with Unity via the "Unity Plugin", install the Unity Plugin from the SDK installer. The plugin lets you connect clients developed in Unity to your Simulate simulations.
To build a Unity client for the simulation you should be familiar with the general simulate-connect-client architecture.
This guide describes setting up the project step by step. In addition, a complete project which uses the Aether Plugin for Unity is available in the Physics demo which can be selected during installation. Once installed, the UnityClient project can be found in
%USERPROFILE%/Hadean/Unity/aetherplugin.tgz
.- 1.
- 2.Add the Aether plugin to the project using Window -> Package Manager menu. Select the
+
menu -> Add package from tarball and select the path where sdk installed the plugin, by default:%USERPROFILE%/Hadean/Unity/aetherplugin.tgz

Adding the Aether Unity Plugin to Unity
- 1.Once added the plugin will be visible in the package list and in the package menu, as in the screenshot below (the version of the plugin will match the version of the SDK).

The Aether Engine Unity Plugin available in Unity
The Unity Client API is very similar to the C++ API described in the repclient documentation, with small changes to make it integrate better with C#.
Here's an overview of an example class used to connect to the Simulate simulation.
using AetherPlugin;
public class Simulation : MonoBehaviour
{
private Repclient _repclient;
// Awake is called before the first frame update - we initialize here
void Awake()
{
// 1. create a connection
_repclient = Repclient.Connection("aether-sdk.mshome.net", "8881");
// 2. authenticate with a player id and a token
_repclient.AuthenticatePlayerIdWithToken(1, "00000000000000000000000000000000");
}
// Update is called once per frame
void Update()
{
// 3. read the received data in the update loop
while (_repclient.IsConnected()) {
byte[] repData = _repclient.ReceiveMessage();
if (repData == null || repData.Length == 0) return;
// 4. decode the data according to the used protocol (see "Using FlatBuffers for marshalling the data")
var message = DecodeMessage(repData);
// use the message
foreach (Entity e in message.Entities) {
// ...
}
}
}
// send a client event to the simulation
void SendEvent()
{
// 5. encode the event data according to the used protocol (see "Using FlatBuffers for marshalling the data")
byte[] eventData = EncodeEvent();
// 6. send the event
_repclient.SendEvent(eventData, false);
}
}
The protocol documentation contains an overview of different approaches to defining a client-server communication protocol. For a project with a Unity client, a protocol defined using FlatBuffers is a good starting point, as it makes it easy to define the data format in one place without having to worry about keeping the C++ and C# definitions synchronized (besides re-running the code generator). It's worth noting that Simulate and the Unity plugin are themselves independent of the used protocol, so FlatBuffers can be replaced with a different approach if needed.
Here's a minimal example of a FlatBuffers protocol file:
// define a structure used for storing coordinates
struct Vec3 {
x: float;
y: float;
z: float;
}
// define a very simple entity
struct Entity {
position: Vec3;
}
// define each message coming from the simulation to contain the current state of all entities
table SimulationMessage {
entities: [Entity];
}
// define a very simple event to be sent to simulation
table ClientEvent {
position: Vec3;
}
For this guide we'll assume the protocol is saved in a file named
protocol.fbs
.Adding FlatBuffers to a Unity project
Once the protocol is defined, the Unity project needs to be configured to use the FlatBuffers protocol. This involves several steps:
- 1.Get
FlatBuffers.dll
andflatc
- 2.Add
FlatBuffers.dll
to the Unity project - 3.Generate the the C# source code for protocol files
- 4.Add the generated files to the project
- 5.Automate the process (optional)
1. Get FlatBuffers.dll and flatc
Flatc is the FlatBuffers compiler which generates the code for encoding and decoding data using FlatBuffers protocol.
FlatBuffers.dll
contains classes necessary to use the generated C# code.There are multiple ways of obtaining these:
- Use the binaries shipped with the example Physics Demo project, by default installed in
%USERPROFILE%\Hadean\Aether Engine Examples\PhysicsDemo\Simulation\Protocol
.
2. Add FlatBuffers.dll to the Unity project
- 1.Create a
FlatBuffers
directory to hold FlatBuffers related files inAssets/
directory of the Unity project. - 2.Drag and drop
FlatBuffers.dll
intoAssets/FlatBuffers
directory.
This will make the FlatBuffers API, used for encoding and decoding data, available in your Unity project.
3. Generate the the C# source code for protocol files
The protocol compiles converts the protocol definitions specified in
protocol.fbs
into C# classes that can then be used to encode and decode the data.The following command will generate the files:
# -n generates C# classes
$ flatc.exe -n protocol.fbs
Here are the generated methods that we're going to use in the example:
SimulationMessage.cs (details omitted for brevity):
public struct SimulationMessage : IFlatbufferObject
{
public static SimulationMessage GetRootAsSimulationMessage(ByteBuffer _bb);
public Entity? Entities(int j);
public int EntitiesLength;
};
Vec3.cs (details omitted for brevity):
public struct Vec3 : IFlatbufferObject {
public static Offset<Vec3> CreateVec3(
FlatBufferBuilder builder,
float X, float Y, float Z
);
};
ClientEvent.cs (details omitted for brevity):
public struct ClientEvent : IFlatbufferObject
{
public static void StartClientEvent(FlatBufferBuilder builder);
public static void AddPosition(FlatBufferBuilder builder, Offset<Vec3> positionOffset);
public static Offset<ClientEvent> EndClientEvent(FlatBufferBuilder builder);
};
4. Add the generated files to the project
Drag and drop the files generated in the previous step into the
Assets/FlatBuffers
directory in the Unity project.The result should look like the following:

hadean screen snippet
5. Automate the process
The steps 3. and 4. of the above process need to be performed every time the protocol definition in
protocol.fbs
is changed. Therfore it's a good idea to automate the process, which can be done using the script below:# download flatc and FlatBuffers.dll
nuget restore -PackagesDirectory "${PSScriptRoot}\packages" ${PSScriptRoot}
# create FlatBuffers directory in the assets directory of the Unity project
$unity_assets_path = "${PSScriptRoot}\UnityProject\Assets\FlatBuffers"
New-Item -ItemType "directory" -Path $unity_assets_path -Force
# get flatc from the downloaded package
$flatc_bin = Get-ChildItem "${PSScriptRoot}\packages" -Filter flatc.exe -Recurse | % { $_.FullName }
# generate csharp files
$flatc_bin -n -o $unity_assets_path "${PSScriptRoot}\protocol.fbs"
# copy FlatBuffers.dll to the assets directory of the Unity project
Copy-Item "${PSScriptRoot}\packages\ek96.FlatBuffers.1.11.0\lib\netstandard2.0\FlatBuffers.dll" -Destination $unity_assets_path
Using FlatBuffers for marshalling the data
Once the protocol has been defined and all the classes and libraries are visible in Unity, the data marshalling can be implemented.
using FlatBuffers;
public class Simulation : MonoBehaviour
{
List<global::Entity> DecodeMessage(byte[] data)
{
ByteBuffer bb = new ByteBuffer(data);
var entities = new List<global::Entity>();
var message = SimulationMessage.GetRootAsSimulationMessage(bb);
for (int i = 0; i < message.EntitiesLength; i++)
{
entities.Add(message.Entities(i).Value);
}
return entities;
}
byte[] EncodeEvent()
{
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
var position = Vec3.CreateVec3(fbb, 0, 0, 0);
ClientEvent.StartClientEvent(fbb);
ClientEvent.AddPosition(fbb, position);
fbb.Finish(ClientEvent.EndClientEvent(fbb).Value);
}
}
Steps to implement FlatBuffers marshalling on the simulation side are similar to the steps on the client side:
- 1.Add the FlatBuffers header-only-library to the CMake project
- 2.Generate C++ source code from the protocol definition and add them to the project
- 3.Call FlatBuffers marshalling methods in order to serialize and deserialize the data.
More details on the usage of FlatBuffers on the server side are available in the protocol documentation and in the PhysicsDemo installed with the SDK.