Skip to content

Unity SDK

The Unity SDK is the UPM package build.rudder.sdk. It ships Rudder.Sdk.dll (the C# SDK) with Unity adapters: a UnityWebRequest transport, PlayerPrefs storage for tokens and the device id, and the Rudder component, which pumps state sync and raises state events on the main thread.

Requires Unity 6000.0 or newer. Current version: 0.1.0. Versions stay 0.x until the API is stable, and any minor release may break it.

Add the Rudder scoped registry and both dependencies to Packages/manifest.json:

{
"scopedRegistries": [
{
"name": "Rudder",
"url": "https://hub.rudder.build/api/packages/rudder/npm/",
"scopes": ["build.rudder"]
}
],
"dependencies": {
"build.rudder.sdk": "0.1.0",
"com.unity.nuget.newtonsoft-json": "3.2.2"
}
}

com.unity.nuget.newtonsoft-json is required: Rudder.Sdk serializes with Newtonsoft.Json and the package does not bundle it.

Namespaces:

  • RudderSdk.Unity: Rudder, RudderConfiguration, RudderState;
  • RudderSdk: RudderClient, SyncedState<T>, exceptions;
  • RudderSdk.Models.*: PlayerProfile, Wallet, CatalogCurrency, StorageItem, …;
  • RudderSdk.Modules: your generated module client.
  1. Create a configuration asset: Assets > Create > Rudder > Configuration.
  2. Set Project Key to the SDK key from Project Settings in the dashboard. The key selects staging or prod.
  3. Add the Rudder component to a GameObject in your startup scene and assign the asset.
FieldDefaultNotes
ProjectKeyRequired.
BaseUrlhttps://api.rudder.buildAPI base URL.
TimeoutSeconds10HTTP request timeout.

Keep the key out of version control: use a gitignored asset and commit an .example copy.

using RudderSdk.Unity;
using UnityEngine;
public class Bootstrap : MonoBehaviour
{
async void Start()
{
var client = Rudder.Initialize();
client.Player.Changed += profile => Debug.Log("wallets: " + profile.Wallets?.Count);
await client.Auth.LoginWithDeviceAsync("global", "en", nickname: "Player");
await client.Player.LoadAsync();
}
}
  • Rudder is a MonoBehaviour that must already be in the scene; the SDK never creates its own GameObject. It survives scene loads, and a duplicate destroys itself.
  • Rudder.Initialize() is synchronous and idempotent. It reads the configuration and returns the RudderClient, and throws when the component or the asset is missing.
  • Rudder.State is NotInitialized, Initializing, Ready or Failed; Rudder.LastError holds the initialization error.
  • Rudder.Client returns the client and throws until Initialize() has run. Rudder.Ready (a Task<RudderClient>) and the static Rudder.Initialized event serve add-ons that load later.

The client exposes Auth, Player, Catalog, Storage, Modules and Sync, the same surface as the C# SDK.

await client.Auth.LoginWithDeviceAsync("global", "en", nickname: "Player");
await client.Auth.LoginWithGoogleAsync(idToken, "global", "en");
await client.Auth.LoginWithAppleAsync(idToken, "global", "en");
await client.Auth.LoginWithCustomAsync(customData, "global", "en", provider: "steam");
await client.Auth.LinkWithGoogleAsync(idToken);
await client.Auth.LinkWithAppleAsync(idToken);
await client.Auth.LinkWithCustomAsync(customData, provider: "steam");
await client.Auth.UnlinkIdentityAsync("google");
  • The device id is a GUID generated once and stored in PlayerPrefs (rudder_device_id). Do not pass SystemInfo.deviceUniqueIdentifier.
  • Access and refresh tokens persist in PlayerPrefs.
  • A 401 triggers one automatic refresh and one retry.
  • Auth.AuthStateChanged fires SignedIn after a login and SignedOut after a logout or a failed refresh. Auth.Logout() drops the session.
  • Every login and token refresh sends platform (from Application.platform) and appVersion (default Application.version).

See Authentication for providers and errors.

Player, Catalog and Storage cache their values. LoadAsync fetches once, ReloadAsync always fetches, and Changed fires on the main thread (the next frame) after every fetch.

The Rudder component calls client.Sync.TickAsync every frame: every 30 seconds (±20%) the SDK polls /sdk/v1/sync and reloads the loaded states whose revision grew. Polling pauses while the application is paused. Do not add your own sync timer.

var profile = await client.Player.LoadAsync();
var gold = profile.Wallets?.FirstOrDefault(w => w.Currency == "gold")?.Balance ?? 0;
long wins = 0;
profile.Counters?.TryGetValue("wins", out wins);
var currencies = await client.Catalog.LoadAsync();

Counters holds the values of number counters that are visible to game clients.

await client.Storage.SaveAsync("save", JsonUtility.ToJson(save));
var items = await client.Storage.ReloadAsync();
var raw = items.FirstOrDefault(i => i.Type == "save")?.Data;
await client.Storage.DeleteAsync("save");

One item per player and type; Data is an opaque string.

Game features are installed modules. Generate a typed client with the rudder CLI and commit it, for example under Assets/Rudder/:

Terminal window
RUDDER_URL=https://api.rudder.build RUDDER_TOKEN=... RUDDER_PROJECT=... \
rudder client generate --lang csharp --out Assets/Rudder/RudderModules.g.cs
using RudderSdk;
using RudderSdk.Modules;
var m = new RudderModules(client);
try
{
var top = await m.Leaderboards.TopAsync(new LeaderboardsTopArgs { Slug = "weekly", Limit = 10 });
}
catch (RudderModuleException e) when (e.Code == LeaderboardsTopErrors.BoardNotFound)
{
Debug.LogWarning(e.Message);
}

There is no editor integration: rerun the command after installing or upgrading modules. Module calls carry an idempotency key and are retried up to 2 times on network errors, 5xx and 409 conflict. See Generated module clients.

Errors are RudderApiException subclasses from RudderSdk: RudderModuleException (422, module business error with Code), RudderAuthException (401, the session is over), RudderNotFoundException (404), RudderRateLimitException (429) and RudderNetworkException (no response). Each carries StatusCode, Code and RequestId.

  • await SDK calls without ConfigureAwait(false), and never block the main thread on SDK tasks.
  • There is nothing to dispose in game code.
  • Static state resets on domain reload, so Play Mode without domain reload works.
  • SDK logs go to Debug.Log* with a [Rudder] prefix.

Import Feature Samples from the Package Manager (select the Rudder SDK package, then Samples). Each scene shows one API:

SceneSDK calls
AuthenticationRudder.Initialize, Auth.LoginWithDeviceAsync, Player.ReloadAsync, Auth.Logout
PlayerPlayer.LoadAsync, Player.Changed, Catalog.LoadAsync
StorageStorage.ReloadAsync, SaveAsync, DeleteAsync
Modulesa generated RudderModules, RudderModuleException

Assign a RudderConfiguration on the Rudder object if the field is empty, then press Play.