# Bootstrap and lifecycle

Namespace `RudderSdk.Unity`. Verified against
`Packages/rudder.sdk/Runtime/Sources/Rudder.cs`,
`RudderConfiguration.cs` and the bundled `Rudder.Core.dll`.

## RudderConfiguration (ScriptableObject)

Create via `Assets > Create > Rudder > Configuration`.

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `ProjectKey` | `string` | — | Required. Issued in the Rudder admin panel. Empty key logs a warning in `OnValidate`. |
| `BaseUrl` | `string` | `https://api.rudder.build` | API base URL. |
| `TimeoutSeconds` | `int` (`[Min(1)]`) | `10` | HTTP request timeout. |

Keep the asset with the real key out of git (this repo uses the git-ignored
`Assets/LiveOpsLocal.asset` pattern).

## Rudder (MonoBehaviour)

`[DefaultExecutionOrder(-1500), DisallowMultipleComponent]`. Put it on a
startup scene object, assign the configuration asset. `Awake` keeps the first
instance (`DontDestroyOnLoad`) and destroys duplicates. `Update` pumps
`_client.Update(Time.deltaTime)` (effects heartbeat and wait-deadline checks
need it — do not call `client.Update` yourself).

Static API:

- `RudderState State` — `NotInitialized` / `Initializing` / `Ready` / `Failed`.
- `Exception LastError` — initialization error when `State` is `Failed`.
- `RudderClient Client` — the Core client; throws `InvalidOperationException`
  until `State` is `Ready`.
- `Task<RudderClient> Ready` — completes with the client after `Initialize`,
  faults on initialization error. Prefer `Initialize()` in game code.
- `event Action<RudderClient> Initialized` — attach point for add-on
  packages; late subscribers must check `State` themselves.
- `RudderClient Initialize()` — synchronous. Reads the serialized
  configuration, creates `RudderClient` via `RudderUnityClientFactory`.
  Idempotent: returns the same client when already `Ready`; resets and
  retries after `Failed`. Throws if the component is not in the scene or no
  configuration is assigned. Does not create a GameObject.

Statics reset on Enter Play Mode without domain reload
(`RuntimeInitializeOnLoadMethod(SubsystemRegistration)`).

## Minimal startup

```csharp
using RudderSdk.Unity;
using UnityEngine;

public class Bootstrap : MonoBehaviour
{
    private async void Start()
    {
        var client = Rudder.Initialize();
        await client.Auth.LoginWithDeviceAsync("global", "en", nickname: "Player");
    }
}
```

`LoginWithDeviceAsync` logs in with the SDK device id (a GUID persisted
in PlayerPrefs under `rudder_device_id`). It is the first awaited call;
afterwards use `client.*` / `Rudder.Client.*`. Tokens persist in PlayerPrefs,
so a second launch can call it again (it refreshes the session). See
[authentication.md](authentication.md) for the Auth service.

Pending scenario effects are fetched after sign-in by the effects heartbeat
(`client.Update`, pumped by `Rudder`). Subscribe to `client.Effects.On*`
before `Scenario.TriggerAsync`.

## Errors

All API errors are `RudderApiException` subclasses from `RudderSdk.Core`:

- `RudderAuthException` — 401; refresh failed, session over
  (`AuthStateChanged(SignedOut)` fires).
- `RudderNotFoundException` — 404.
- `RudderRateLimitException` — 429.
- `RudderNetworkException` — no response / timeout.

`RudderApiException` exposes `StatusCode` (int), `Code` (string),
`RequestId` (string). The client retries a 401 once after a single-flight
token refresh — game code does not implement that retry. Catch and surface
`exception.Message`; do not swallow errors.

Removed APIs (do not use): `Rudder.Initialize(configuration)`,
`Rudder.Auth`-style static service shortcuts, `client.Scenarios`,
`BuyAsync`, `LoginViaDeviceAsync`, `AuthorizeWithDeviceAsync`,
`Scenario.RestoreAsync`.
