Skip to content

Unity client

Use the Unity client when you want generated Golem protocol code, transport handling, and scene helpers inside a Unity project. golem-bake emits C# classes for your schemas, the Unity package opens WebSocket or WebTransport connections, and the prefab bridge can spawn GameObjects for synced entities.

Keep the Golem project root as the folder that contains golem.yaml, then place the Unity project below it:

MyGame/
golem.yaml
cmd/server/
schemas/
Unity/
Assets/
Packages/

In Unity, add the Golem package and WebTransport package to Packages/manifest.json:

{
"dependencies": {
"io.demiurgos.golemengine": "file:C:/Demiurgos/golem-engine/golem-unity",
"io.demiurgos.webtransport": "file:C:/Demiurgos/webtransport-csharp/artifacts/upm/io.demiurgos.webtransport"
}
}

For registry installs, use the published package versions instead of file: paths. The Golem Unity package depends on the WebTransport package, but local sample projects usually list both packages explicitly so Unity can resolve both local folders.

Add the C# client integration to golem.yaml and point it at folders inside your Unity project:

simulation:
dimensions: 3 # optional; include when your Unity game needs PosZ
integrations:
go-server:
out: internal/synced/
package: synced
csharp-client:
out: Unity/Assets/GolemGenerated/
package: MyGame.GolemGenerated
unity:
out: Unity/Assets/GolemViews/
package: MyGame.GolemGenerated

csharp-client emits the protocol client: ClientFactory, EntityManager, SyncedPlayer-style entity classes, command builders, and protobuf codec wrappers for your schema. The optional unity integration emits simple MonoBehaviour view scaffolds per entity type.

In Unity, open Golem > Settings… and set Project Root to the folder that contains golem.yaml. golem.yaml stays the source of truth for generated output folders; the Unity settings page only displays the resolved csharp-client.out path.

Use Golem > Generate Code to run golem-bake from that project root. The default Bake Command Mode is Go Command, which runs:

Terminal window
go run golem-engine/cmd/golem-bake

Use Path Executable when golem-bake is installed on PATH, or Custom Command when your team pins a project-local binary such as Tools/golem-bake.exe.

For WebTransport, use the default Golem transport and datagram state-update lane:

srv, rt := synced.NewServer(golem.ServerConfig{
Addr: ":4433",
DevSelfSignedCert: true, // local development only
})
rt.Commands.BindAllHandlers(func(sess *golem.Session, err error) {
log.Println("command error:", err)
})

For WebSocket, explicitly select the stream state-update lane:

srv := golem.NewServer(golem.ServerConfig{
Addr: ":8080",
Transport: golem.TransportWebSocket,
StateUpdateLane: golem.StateUpdateLaneStream,
})

Command routing is the same as the JavaScript and Go clients. The generated C# runtime batches commands into a ClientPacket, so the server should use the generated command router:

rt.Commands.BindStreamHandler(func(sess *golem.Session, err error) {
log.Println("command error:", err)
})

Create a generated client and connect it to the endpoint:

using MyGame.GolemGenerated;
var client = ClientFactory.CreateClient();
client.Connect("https://localhost:4433/wt");

For scene wiring, subclass GolemClientBehaviour and return the generated client. Pass a WebTransport transport factory when your project uses WebTransport:

using GolemEngine.Unity;
using MyGame.GolemGenerated;
using WebTransport;
public sealed class GameRealtimeClient : GolemClientBehaviour
{
protected override GameClient CreateClient()
{
return ClientFactory.CreateClient(
() => new GolemWebTransportTransport(new WebTransportClientOptions
{
AllowUntrustedCertificates = true,
}));
}
}

The component exposes the URL in the Inspector and can connect automatically on Start. Use AllowUntrustedCertificates only for local development with generated self-signed certificates.

For each command schema, generated C# includes a builder on CommandBuilders. Pass the result to Send:

client.Send(CommandBuilders.BuildMoveCommand(playerEntityId, dx, dy));

Send encodes one command as a ClientMessage, batches one or more messages into a ClientPacket, and keeps each reliable packet under 32000 bytes.

On WebTransport, generated C# clients also expose reliable datagram command helpers for commands that should avoid waiting behind unrelated reliable stream traffic:

client.SendReliableUnordered(CommandBuilders.BuildMoveCommand(playerEntityId, dx, dy));
client.SendReliableOrdered(CommandBuilders.BuildMoveCommand(playerEntityId, dx, dy));

Use the stream path first. Reach for reliable unordered or ordered datagrams when a small command should use a separate WebTransport datagram lane.

Create a GolemPrefabRegistry asset and add one entry per entity type, such as Player or Monster. Add GolemEntitySpawner to your scene and bind it to the generated entity manager after creating the client:

spawner.Bind(client.Entities);

When an entity spawns, the spawner looks up a prefab by generated entity type name, instantiates it, and binds any GolemEntityView<T> or GolemTransformBinding components on the prefab. GolemTransformBinding copies the generated PosX and PosY properties into the GameObject transform and can smooth movement between updates. In 3D projects it also copies PosZ; 2D projects keep the prefab’s existing transform.position.z.

For a 3D project, move server-side entities with SetPosition3D(x, y, z) so the generated C# client receives all three coordinates.

If your schemas include events, ClientFactory.CreateClient() wires an EventManager. Global and session events can be handled through generated OnXxx methods on the event manager, while entity events are reflected onto methods on the bound synced entity when present.

If your schemas include world data, the generated WorldManager stores the latest data and invokes typed OnXxxUpdate callbacks when the server sends initial or refreshed world data.

The top-level Golem menu helps with local Unity project setup:

  • Generate Code runs the configured bake command from the folder containing golem.yaml.
  • Run Server opens the configured server command in an external terminal at the project root. Unity does not own, stop, or restart that process.
  • Validate Setup checks the project root, bake command, generated output folder, prefab registry, and scene spawner.
  • Configure Current Scene creates or selects the prefab registry, entity spawner, and client object.
  • Create menu items create individual scene/setup assets.
  • Settings… opens the project-scoped Golem settings.

The Asset Folder setting is only for Unity-side assets created by the scene setup tools. Generated C# output paths come from golem.yaml.

Unity WebTransport failures often happen before Golem’s reliable stream protocol starts, so check the transport setup first:

  • Use the WebTransport endpoint, not the WebSocket endpoint. A typical local URL is https://localhost:4433/wt; :8080 is commonly used by WebSocket examples.
  • The server must run WebTransport over HTTP/3/QUIC with TLS. For local development, set DevSelfSignedCert: true and use a loopback URL.
  • Browser-style ws:// and wss:// URLs are for WebSocket only. WebTransport uses https://.
  • Production origins must be allowed by server config when the page/API port differs from the WebTransport port.

The Unity logs include the transport, redacted URL, phase, and error category. If a failure says phase=connect, check the URL, TLS certificate, UDP/QUIC reachability, and origin policy before looking at generated entity or command code.

The reliable stream keeps each logical packet under 32000 bytes. WebTransport datagrams use a 1200-byte cap before protocol overhead. Generated C# managers apply compact datagram state automatically when using WebTransport; WebSocket and custom transports without datagrams should use StateUpdateLaneStream.

See also Channels and transports, State updates, and Client commands.