Template Guide
Customise the NetCrafter Relay code generator output with template overrides.
NetCrafter Relay generates code by substituting placeholders in .tpl text files. The nine built-in templates live at:
Assets/PivecLabs/NetCrafterRelay/Templates/
You must never edit files in this folder directly. The Template Override System lets you customise the output for a specific schema while leaving the global templates untouched.
How the override system works#
When Use Custom Templates is enabled in Settings → Project Settings, the generator checks the schema's override folder before loading each template:
Definitions/{SchemaName}/Templates/{TemplateName}.tpl
If the override file exists, it is used instead of the global template. If it does not exist, the global template is used as a fallback. You can override any subset of the nine templates — you do not need to provide all of them.
Setting up overrides#
- Open Settings → Project Settings for your schema.
- Enable Use Custom Templates.
- Click Create Override Folder.
This creates Definitions/{SchemaName}/Templates/ and copies all nine global templates into it. Each copied file receives a header comment:
// NetCrafter Template Override
// Schema: MyGame
// Template: RequestClass.tpl
// Modified: 2026-06-06
// This file overrides the global template for this schema only.
// Delete this file to revert to the global template.
The Template Files grid shows a green [✓] next to each template that exists in the override folder. Templates marked [ ] use the global fallback.
Reverting an override#
Click Reset next to any template in the grid. This deletes the override file; the next generation will use the global template for that file. Alternatively, delete the file manually from Definitions/{SchemaName}/Templates/.
Template reference#
RequestClass.tpl
Generates one file per ClientToHost/ClientToHostBroadcast message: {MessageName}Request.cs.
| Placeholder | Replaced with |
|---|---|
{{NAMESPACE}} |
The C# namespace from Project Settings |
{{REQUEST_NAME}} |
The message name |
{{FIELDS}} |
Public field declarations, one per message field |
{{WRITE_FIELDS}} |
writer.Write*(value) statements for Serialize() |
{{READ_FIELDS}} |
req.field = reader.Read*() statements for Deserialize() (used host-side by HostActionRouter) |
EventClass.tpl
Generates one file per HostToClient event: {EventName}Event.cs.
| Placeholder | Replaced with |
|---|---|
{{NAMESPACE}} |
The C# namespace |
{{EVENT_NAME}} |
The event name |
{{FIELDS}} |
Public field declarations |
{{WRITE_FIELDS}} |
writer.Write*(value) statements for Serialize() (built host-side before broadcasting) |
{{READ_FIELDS}} |
ev.field = reader.Read*() statements for Deserialize() (used by the receiving peer) |
ModelClass.tpl
Generates one file per Data Definition: {ModelName}.cs.
| Placeholder | Replaced with |
|---|---|
{{NAMESPACE}} |
The C# namespace |
{{MODEL_NAME}} |
The model name |
{{FIELDS}} |
Public field declarations |
{{WRITE_FIELDS}} |
Serialisation statements for WriteTo(RelayWriter) |
{{READ_FIELDS}} |
Deserialisation statements for ReadFrom(RelayReader) |
RelayConnectionManager.tpl
Generates one RelayConnectionManager.cs per schema — owns the StunTurnClient, the join/host flow, and the send/receive envelope.
| Placeholder | Replaced with |
|---|---|
{{NAMESPACE}} |
The C# namespace |
{{RELAY_HOST}} |
Relay host from Relay Settings |
{{RELAY_PORT}} |
TURN port |
{{RENDEZVOUS_URL}} |
Rendezvous service URL |
{{CREDENTIAL_MODE}} |
StaticSecret or RestApi |
{{EVENT_SWITCH}} |
One case block per HostToClient event |
{{EVENT_HANDLERS}} |
One handler stub method per HostToClient event |
HandlerSwitch.tpl
Generates the case block injected into {{EVENT_SWITCH}}. One instance is generated per HostToClient event.
| Placeholder | Replaced with |
|---|---|
{{EVENT_NAME}} |
The event name |
EventHandler.tpl
Generates the handler method stub injected into {{EVENT_HANDLERS}}. One instance per HostToClient event.
| Placeholder | Replaced with |
|---|---|
{{EVENT_NAME}} |
The event name |
HostActionRouter.tpl
Generates one HostActionRouter.cs per schema — the host-side logic that used to be a separate Java server extension. It compiles straight into the same client build; there's no deploy step.
| Placeholder | Replaced with |
|---|---|
{{NAMESPACE}} |
The C# namespace |
{{HANDLER_CASES}} |
One case block per Host Action, dispatching to its handler method |
{{HANDLER_METHODS}} |
One handler method per Host Action (see HostActionHandler.tpl) |
HostActionHandler.tpl
Generates one handler method per Host Action, injected into {{HANDLER_METHODS}}.
| Placeholder | Replaced with |
|---|---|
{{HANDLER_NAME}} |
The Host Action's handler name |
{{METHOD_BODY}} |
Trigger deserialization, response construction, and the BroadcastAll/SenderOnly/TargetUser/Custom dispatch logic |
RelayConfig.tpl
Generates RelayConfig.json — a small config file with the relay connection settings, replacing the old SFS3 zone XML entirely (no zone/room/AOI concepts apply here).
| Placeholder | Replaced with |
|---|---|
{{RELAY_HOST}} |
Relay host from Relay Settings |
{{RELAY_PORT}} |
TURN port |
{{RENDEZVOUS_URL}} |
Rendezvous service URL |
{{CREDENTIAL_MODE}} |
StaticSecret or RestApi |
Example: add a log line to every request#
This adds a Debug.Log call at the top of every request's Serialize() method.
- Enable Use Custom Templates and click Create Override Folder.
- Open
Definitions/{SchemaName}/Templates/RequestClass.tpl. - Find the
Serializemethod body and add one line before theRelayWriteris created:
public byte[] Serialize()
{
Debug.Log("[Net] Sending {{REQUEST_NAME}}");
var writer = new PivecLabs.NetCrafterRelay.RelayWriter();
{{WRITE_FIELDS}}
return writer.ToArray();
}
- Click Generate All Files. Every request class in the schema will now include the log line with the correct message name substituted in.
Placeholder validation#
Each time you generate with Use Custom Templates on, NetCrafter Relay checks every override template for required placeholders and logs a [NetCrafter Relay] Warning in the Unity console for any that are missing. Generation still proceeds, but the output will be malformed if a required placeholder is absent. The same check runs when you click Create Override Folder.