Skip to content

01 — Setup

Before any netcode, you need two things in your Unity project:

  1. the com.lattice.netcode package (the managed C# binding), and
  2. the native plugin liblattice for each platform you build for.

The managed code is useless without the native library — every call ultimately P/Invokes into liblattice (Linux .so, Windows .dll, macOS .bundle, and so on).

Verified against: bindings/lattice-unity/com.lattice.netcode/package.json, bindings/lattice-unity/com.lattice.netcode/Plugins/README.md.

Requirements

  • Unity 2021.3 or newer. The package manifest declares "unity": "2021.3"; the sample project targets 2022.3 LTS.
  • A build of liblattice for your target platform (see step 2).

1. Add the com.lattice.netcode package

The binding is a standard Unity Package Manager (UPM) package. The sample references it by local file path in Packages/manifest.json:

Packages/manifest.json
{
  "dependencies": {
    "com.lattice.netcode": "file:../../../bindings/lattice-unity/com.lattice.netcode",
    "com.unity.modules.imgui": "1.0.0"
  }
}

Verified against: samples/unity-tictactoe/Packages/manifest.json.

You have three practical options:

Point manifest.json at the package folder on disk. Best while developing against a checkout of the repo.

"com.lattice.netcode": "file:/absolute/or/relative/path/to/com.lattice.netcode"

Copy the whole com.lattice.netcode/ folder into your project's Packages/ directory. Unity imports it as an embedded package.

Add it via Window → Package Manager → + → Add package from git URL if you host the binding in a git repository. (The sample uses the local-path form.)

After Unity resolves the package you will have the Lattice and Lattice.Interop namespaces available, plus the Lattice.Runtime assembly your own asmdef can reference.

What the package contains (abridged)
com.lattice.netcode/
├── package.json
├── Runtime/
│   ├── Lattice.Runtime.asmdef          reference this from your game asmdef
│   ├── NetworkRunner.cs                 StartGame / Connect / Tick / Spawn / Rpc / SendEvent …
│   ├── NetworkObject.cs                 managed view of a replicated object
│   ├── NetworkTypeSchema.cs             type registration (FieldSpec / RegisterType)
│   ├── Attributes.cs                    [Networked] / [Rpc] / [OnChanged]
│   └── Interop/LatticeNative.cs         the P/Invoke surface (public ABI only)
├── Editor/…                             prefab-catalog tooling
└── Plugins/…                            native lib per platform

Verified against: bindings/lattice-unity/README.md (Layout section).

Reference the runtime assembly

Your gameplay scripts live in their own assembly definition. Reference Lattice.Runtime so they can see NetworkRunner and friends — exactly as the sample's asmdef does:

Assets/YourGame/Scripts/YourGame.asmdef references
TicTacToe.Sample.asmdef  →  references Lattice.Runtime

Verified against: samples/unity-tictactoe/README.md (project layout) and samples/unity-tictactoe/Assets/TicTacToe/Scripts/TicTacToe.Sample.asmdef.

2. Install the native plugin per platform

Each platform's build of the core goes under Plugins/<Platform>/<arch>/. Unity's per-plugin import settings restrict each binary to its target. The DllImport name is "lattice", which Unity resolves to the correct file for the running platform.

Verified against: bindings/lattice-unity/com.lattice.netcode/Runtime/Interop/LatticeNative.cs:231 (public const string Lib = "lattice";).

Platform File in Plugins/… How it's produced
Linux x86_64 Linux/x86_64/liblattice.so native-snapshot/build.shchecked in, headless-verified
Windows x86_64 Windows/x86_64/lattice.dll core build-windows.shchecked in
macOS (universal) macOS/lattice.bundle core macOS build (arm64 + x86_64)
Android arm64 Android/arm64-v8a/liblattice.so NDK build
iOS iOS/liblattice.a static, IL2CPP

Verified against: bindings/lattice-unity/com.lattice.netcode/Plugins/README.md.

Only Linux and Windows binaries are checked in

In the repository, only the Linux .so and Windows .dll are present under Plugins/. The macOS/, Android/, and iOS/ folders exist as import-setting placeholders (.meta files) but you must build those binaries yourself from the core's cross-platform build (task CP1) and drop them into the matching folder. The binding code is identical across platforms because it targets the stable C ABI.
Verified against: Plugins/ directory listing — Plugins/Linux/x86_64/liblattice.so and Plugins/Windows/x86_64/lattice.dll are the only binaries; other platform folders contain only .meta files.

Building the Linux .so yourself

If you're working from the repo and the .so is missing, build it from the binding's decoupled snapshot of the core:

cd bindings/lattice-unity/native-snapshot
bash build.sh          # → native-snapshot/build/liblattice.so

Verified against: samples/unity-tictactoe/headless/run.sh:11-15 and bindings/lattice-unity/README.md ("Building & running").

Set the plugin import settings

In the Unity editor, select each native file under Plugins/ and, in the Inspector's Plugin import settings, tick only the platform/architecture it belongs to (e.g. the .so → Linux x86_64 only). This prevents Unity from trying to load the wrong binary on the wrong platform.

This step needs the editor

Plugin import settings are editor-only metadata. The headless verification path (below) resolves the library a different way, so it doesn't exercise this — but a real Unity build does.

3. Verify it loads

There is no editor in the reference environment, so the binding is proven by a headless .NET harness that points DllImport("lattice") at the built .so via a custom resolver and drives a real two-player match. You can run it to confirm your native build works before touching Unity:

cd samples/unity-tictactoe/headless
bash run.sh          # loopback transport
bash run.sh udp      # real localhost UDP

A healthy run ends with:

 RESULT: 55/55 checks passed, 0 failed.
 ALL HEADLESS CHECKS PASSED.

Verified against: samples/unity-tictactoe/headless/run.sh, samples/unity-tictactoe/headless/Program.cs, and samples/unity-tictactoe/README.md ("Latest result").

In Unity itself, the native library is resolved automatically by the plugin import settings — you don't register a resolver. If a call throws DllNotFoundException, the plugin isn't present (or isn't enabled) for your current platform.


Next: 02 — Your first runner, where you create a NetworkRunner and start a host and a client.