Unity Game Scenarios

Use the Unity SDK through real game lifecycle flows.

These examples map the JavaScript reference concepts to Unity-style method names and engine lifecycle points.

Concept Parity

Same Persistly model, Unity method names.

Account, slot, accountData, conflict, and cleanup behavior match JavaScript and Godot. Only the API style changes.

Boot Unity scenes from local slots first; cloud sync should not block loading unless your game explicitly needs a fresh check.

Signed-in restore uses your backend to store accountId plus accountSessionToken, then ConfigureAsync restores that session.

RefreshSlotAsync pulls the named cloud slot after account attach without exposing internal save identifiers to normal game code.

AccountData holds shared state across all slots: bundles, shared inventory, settings, and validated currency balances.

ClearLocalAccountAsync is local logout. DeleteSlotAsync and DeleteAccountAsync are permanent erasure flows.

Cross-Device Restore

Restore a signed-in player, then refresh the named slot.

Persistly does not recover anonymous local saves by email alone. Your trusted backend stores the Persistly account session after first sync.

C#
// Device A: after sign-in and first successful sync.
await PersistlyGameSaves.Shared.ForceSyncDataAsync();

var session = PersistlyGameSaves.Shared.GetAccountSession(includeToken: true);
await MyBackend.SavePersistlyLinkAsync(
    userId,
    session.AccountId,
    session.AccountSessionToken);

// Device B: same player signs in later.
var link = await MyBackend.GetPersistlyLinkAsync(userId);

await PersistlyGameSaves.ConfigureAsync(new PersistlyGameSavesSettings("ps_test_...")
{
    PlayerRef = userId,
    AccountId = link.AccountId,
    AccountSessionToken = link.AccountSessionToken,
});

await PersistlyGameSaves.Shared.RefreshDataAsync();
var loaded = await PersistlyGameSaves.Shared.LoadDataAsync<PlayerData>();

Shared Account State

Use accountData for state shared across all slots.

Use this for bundles, shared inventory, settings, and display balances after trusted purchase validation.

Account Data

Patch shared state, inspect it locally, then sync the account.

PatchAccountDataAsync shallow-merges top-level keys. Null deletes a top-level key; nested objects and arrays are replaced.

C#
await PersistlyGameSaves.Shared.PatchAccountDataAsync(
    "{\"diamonds\":200,\"bundles\":{\"starter\":true},\"sharedInventory\":[1,25,35]}");

var accountDataJson = PersistlyGameSaves.Shared.GetAccountDataJson();
var account = PersistlyGameSaves.Shared.InspectAccount();

await PersistlyGameSaves.Shared.ForceSyncAccountAsync(new PersistlySyncOptions
{
    BypassCooldown = true,
});

Lifecycle

Save locally first; force sync at Unity lifecycle boundaries.

Async work during quit is not guaranteed on every platform, so also sync on checkpoints, pauses, and manual save moments.

C#
await PersistlyGameSaves.Shared.SaveDataAsync(currentData);

private async void OnApplicationPause(bool pause)
{
    if (pause)
    {
        await PersistlyGameSaves.Shared.ForceSyncDataAsync();
    }
}

private async void OnApplicationQuit()
{
    await PersistlyGameSaves.Shared.ForceSyncDataAsync();
}

Cleanup

Keep logout and permanent erasure separate.

Use local clear for account switching. Use delete methods only behind explicit danger UI.

C#
// Logout or switch local player. Cloud data stays intact.
await PersistlyGameSaves.Shared.ClearLocalAccountAsync();

// Permanent slot/account erasure. Use only behind explicit danger UI.
await PersistlyGameSaves.Shared.DeleteSlotAsync("autosave");
await PersistlyGameSaves.Shared.DeleteAccountAsync();