Unity SDK

Unity runtime SDK plus a playable Last Beacon sample project.

The Unity SDK now compiles inside a real Unity editor, passes edit-mode tests, and ships with a generated Last Beacon sample scene that exercises Persistly create, load, and sync behavior.

Current State

What exists now and what still remains.

Contract bundle stays pinned to the same save, version, and sync semantics as the JavaScript reference SDK.

Typed create, load, and sync flows already map directly to explicit save IDs and optimistic concurrency.

A real SampleProject/ now exists with a generated LastBeacon.unity scene and local edit-mode test coverage. Remaining work is packaging polish and release discipline, not basic runtime viability.

Runtime Surface

What the package exposes today.

PersistlyClient handles create, load, sync, and local cache coordination.

PersistlyCreateSaveRequest and PersistlySyncSaveRequest accept JSON object strings for state and optional metadata.

PersistlySyncResponse models both accepted and conflict outcomes while keeping the canonical save payload intact.

PersistlySave returns canonical metadataJson and stateJson strings so Unity projects can pipe them directly into JsonUtility or custom serializers.

Install

Use the public Unity package source, not a private checkout path.

Open Package Manager -> Add package from git URL -> https://github.com/persistly/persistly-sdk-unity.git

Official repository: https://github.com/persistly/persistly-sdk-unity

Setup

Construct the client with a runtime key and the public API origin.

using Persistly.Unity;

var client = new PersistlyClient(new PersistlyClientOptions(
    "https://api.persistly.app",
    "ps_test_..."
));

var created = await client.CreateSaveAsync(new PersistlyCreateSaveRequest(
    stateJson: "{\"coins\":418,\"checkpoint\":\"vault\"}",
    metadataJson: "{\"characterName\":\"Ayla\",\"slotLabel\":\"Mage\"}",
    externalUserId: "auth0|player-184"
));

var sync = await client.SyncSaveAsync(created.SaveId, new PersistlySyncSaveRequest(
    stateJson: "{\"coins\":612,\"checkpoint\":\"reactor\"}",
    baseVersion: created.Version,
    metadataJson: "{\"characterName\":\"Ayla\",\"slotLabel\":\"Mage\"}"
));

Playable Sample

Use Last Beacon to validate the full flow inside Unity.

The sample project lives under sdks/unity/SampleProject and includes a generated Assets/Scenes/LastBeacon.unity scene.

The game uses a local profile store, explicit Persistly configuration fields, and the same create/load/sync contract as the JavaScript and Godot tracks.

The UI is intentionally asset-light and built with IMGUI so the sample proves network and persistence behavior without requiring art pipelines.

Behavior Notes

What is enforced by the SDK itself.

Payload sizes are validated locally before runtime requests leave the game client: 16 KB for metadata and 256 KB for state.

The client caches canonical saves in memory and can infer baseVersion for sync if the save has already been loaded or created in-process.

Structured API errors map to typed exceptions such as invalid request, unauthorized, conflict, rate limited, and payload too large.

Validation

Use the public sample and repository checks as the verification path.

Run the Last Beacon sample scene from the official Unity repository and verify create, load, sync, and conflict handling with a ps_test_ key first.

Keep the same API origin and save contract when you move from the sample into your production game project.