by Pivec Labs
Getting Started Setup walkthrough

Getting Started

Install to first generated file in under 10 minutes with NetCrafter Relay.

This guide walks you from a fresh Unity project to a running NetCrafter Relay schema that generates working co-op network code.

01

1. Install the asset#

Import the NetCrafter Relay .unitypackage into your project via Assets → Import Package → Custom Package. After import the following structure will appear under Assets/PivecLabs/NetCrafterRelay/:

text
Documentation/      — these docs
Editor/             — editor window and code-generation tools
Examples/           — example schemas
Plugins/x86_64/     — NetCrafterRelayNative.dll (Windows only)
Scripts/            — ScriptableObject definitions + the pure C# relay client
Templates/          — built-in code templates
02

2. Open the NetCrafter Relay editor window#

text
Unity menu → Tools → Pivec Labs → NetCrafter Relay

The window opens with four top-level sections in the toolbar: Definition, Code, Scenes, and Settings. Resize it to at least 1100 × 650 if controls appear clipped.

03

3. Create a schema (Definition)#

A Definition is a named collection of messages, events, models, and host actions. Each definition generates its own isolated set of C# files.

  1. In the schema bar at the very top of the window, click Create Definition.
  2. Name it (e.g. MyGame). A folder is created at Assets/PivecLabs/NetCrafterRelay/Definitions/MyGame/.

You can switch between definitions using the dropdown in the schema bar.

04

4. Configure Relay settings#

Click Settings in the top toolbar, then Relay Settings in the sidebar.

Field Value to set
Relay Host Your own coturn endpoint (required, no default — see Server Deployment Guide)
Relay Port 3478 (TURN default)
Rendezvous URL Your own rendezvous service (required, no default — see Server Deployment Guide)

Leave all other fields at their defaults for now. Click Save Settings.

Allow HTTP in Player Settings — a fresh Unity project blocks this by default. The Rendezvous URL above is a plain http:// endpoint, not https://. Unity 2022+ projects default Player Settings → Other Settings → Configuration → Allow downloads over HTTP to Not allowed — with that default, the very first connection attempt throws InvalidOperationException: Insecure connection not allowed from UnityWebRequest.BeginWebRequest(), before any relay-specific code even runs. Set it to Always allowed now, before you test anything — Allowed in development builds is enough for Editor testing, but a real build for players needs Always allowed, so there's no reason to set it to anything less permanent. Confirmed live: a brand-new project with this left at its default fails this way on the very first host/join attempt, with every other setting correct.

05

5. Define a model (Data Definition)#

Models are plain data classes that can be nested inside messages and events. Create a PlayerState model:

  1. Click Definition in the top toolbar, then Data Definitions in the sidebar.
  2. Click Create Data Definition. Name it PlayerState.
  3. Add fields:
Name Type
position Vector3
health int
username string
isAlive bool
06

6. Define a message (ClientToHost)#

Messages sent from a client to the host generate a {Name}Request class with a Send() method.

  1. Click Definition → Messages in the sidebar.
  2. Click Create Gameplay Message. Name it PlayerMove.
  3. Set Direction to ClientToHost.
  4. Set Host Handler Name to HandlePlayerMove (this must match a Host Action you add next).
  5. Add fields:
Name Type
playerId PlayerId
position Vector3
speed float

Add a matching Host Action

  1. Click Host Actions in the sidebar.
  2. Click Create Host Action. Set Handler Name to HandlePlayerMove.

This logic runs only on whichever peer is currently hosting — there's no separate server process to deploy.

07

7. Define an event (HostToClient)#

Events sent from the host to a client generate a {Name}Event class with Serialize()/Deserialize() methods.

  1. Click Messages in the sidebar. Click Create Gameplay Message.
  2. Name it PlayerStateUpdate. Set Direction to HostToClient.
  3. Set Host Handler Name to HandlePlayerStateUpdate.
  4. Add a field: name state, type string.

Note: To use a nested model type such as PlayerState as a field type, open the generated .asset file in a text editor and set type: PlayerState directly. The editor field-type dropdown currently shows only primitive types.

Add a matching Host Action with handler name HandlePlayerStateUpdate.

08

8. Run Generate All Files#

  1. Click Code in the top toolbar, then Build Code in the sidebar.
  2. Click Validate Definition first to confirm there are no errors.
  3. Click Generate All Files.

Generated files appear in:

text
Assets/PivecLabs/NetCrafterRelay/Definitions/MyGame/Generated/Client/
Assets/PivecLabs/NetCrafterRelay/Definitions/MyGame/Generated/Host/
09

9. What was generated#

For the schema above, the generator produces:

File Description
PlayerMoveRequest.cs Send a PlayerMove message to the host
PlayerStateUpdateEvent.cs Receive a PlayerStateUpdate event from the host
PlayerState.cs Serialisable data model
RelayConnectionManager.cs MonoBehaviour that manages the relay connection (Client folder)
HostActionRouter.cs Host-side logic — runs only when this peer is hosting (Host folder)
10

10. Set up your scene#

The Scene Assistant automates the boilerplate of wiring a multiplayer scene.

Create the ConnectionManager prefab

  1. Click Scenes in the top toolbar, then Prefab Generator in the sidebar.
  2. Click Create ConnectionManager Prefab.

The generator finds the INetCrafterConnection-implementing type in your Generated/Client/ folder, wraps it in a prefab, and saves it to Prefabs/RelayConnectionManager.prefab — a sibling of Generated/, not inside it, since this prefab holds your actual relay host/rendezvous URL/TURN credentials once you configure it and is never touched by code regeneration. If the script is not found, generate client code first (step 8).

Create the scene

  1. Click Scene Assistant in the sidebar.
  2. Confirm the green banner shows that the prefab was found.
  3. Optionally enable Add Event Dispatcher — this adds a NetCrafterEventDispatcher GameObject that lets any script subscribe to host events without touching the generated file (see step 13).
  4. Click Create Multiplayer Scene.

The assistant creates a new scene containing:

  • A Main Camera
  • A ConnectionManager GameObject (instantiated from the prefab)
  • An EventDispatcher GameObject (if the toggle was enabled)
  • A NetworkManager empty GameObject (reserved for future use)

The scene is saved to Definitions/{Name}/GameScene.unity and opened in the editor. You can rename it using the Scene Name field before clicking Create.

Add to an existing scene

If you already have a scene open, click Add to Existing Scene instead. This adds only the ConnectionManager (and EventDispatcher) — it does not add a camera or NetworkManager. If a ConnectionManager is already present, a confirmation dialog appears before a second one is added.

11

11. Add the ConnectionManager to a scene manually#

If you prefer not to use the Scene Assistant:

  1. Create an empty GameObject in your scene. Name it ConnectionManager.
  2. Attach the generated RelayConnectionManager component to it.
  3. Drag this schema's RelaySettings.asset (Definitions/{Name}/RelaySettings.asset) onto its Connection Settings field — the same asset the Relay Settings tab edits. (Prefab Generator does this automatically; it's only a manual step here because you're skipping the prefab.)

The ConnectionManager is a singleton with DontDestroyOnLoad. Call Connect() from a script when the game starts — with no join code set, it hosts a new session; call UpdateHost(joinCode) first to join an existing one:

csharp
void Start()
{
    // Hosting a new session:
    RelayConnectionManager.Instance.Connect();

    // Or, to join an existing session:
    // RelayConnectionManager.Instance.UpdateHost("GAME-4892");
    // RelayConnectionManager.Instance.Connect();
}
12

12. Send a request#

Populate the generated request class and call Send():

csharp
using PivecLabs.MyGame.Generated;

public class PlayerController : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var request = new PlayerMoveRequest
            {
                playerId = RelayConnectionManager.Instance.LocalUserId,
                position = transform.position,
                speed    = 5.0f
            };
            request.Send(RelayConnectionManager.Instance, reliable: true);
        }
    }
}
13

13. Handle an event#

Option A — Fill in the generated stub. Open RelayConnectionManager.cs and complete the stub method:

csharp
private void OnPlayerStateUpdate(PlayerStateUpdateEvent ev)
{
    // ev.state is a deserialized PlayerState object
    Debug.Log($"Player at {ev.state.position}, health {ev.state.health}");
}

Option B — Subscribe via EventDispatcher. From any MonoBehaviour in the scene, subscribe to the event by command name. This approach does not require editing the generated file:

csharp
private void OnEnable()
{
    NetCrafterEventDispatcher.Instance.Subscribe("PlayerStateUpdate", OnPlayerState);
}

private void OnDisable()
{
    NetCrafterEventDispatcher.Instance.Unsubscribe("PlayerStateUpdate", OnPlayerState);
}

private void OnPlayerState(object payload)
{
    var ev = (PlayerStateUpdateEvent)payload;
    Debug.Log($"Player at {ev.state.position}, health {ev.state.health}");
}

Both options can be used simultaneously — the dispatcher fires first, then the stub. See the API Reference for full EventDispatcher details.

14

Next steps#