# UPM Tarball Installation

This guide applies to `core-igp-0.3.4.tgz` on Unity `2022.3`. The shorter artifact file name does not change the internal UPM package name, `cn.indiegp.sdk.unity`.

The public UPM tarball contains the complete Core runtime in `Plugins/IGP.UnitySDK.dll`. The public types and call sequences below are the supported usage contract. Editor integration, documentation, and examples remain available in the package; use the matching `.unitypackage` only when a source distribution is specifically needed.

## Package Contents

| Path | Purpose |
| --- | --- |
| `Plugins/IGP.UnitySDK.dll` | Core runtime API and implementation. |
| `Editor/` | Unity editor integration source. |
| `Documentation~/` | Installation, API behavior, and data structure references. |
| `Samples~/` | Explicitly imported Unity samples. |
| `package.json` | UPM package ID, version, and dependencies. |

The UPM carrier is complete for runtime use. It does not include PDB files or the source carrier's runtime implementation files; that packaging distinction does not change the available API or behavior.

## Install

1. Open `Window > Package Manager`.
2. Open the `+` menu and choose `Add package from tarball`.
3. Select `core-igp-0.3.4.tgz`.
4. Wait for Unity to resolve `com.unity.nuget.newtonsoft-json` and compile the project.

The tarball contains the complete Core package. Multiplayer, Compliance, and Game Kit remain separate optional public packages.

For a manifest-based installation, keep the tarball at a stable path and add:

```json
"cn.indiegp.sdk.unity": "file:../LocalPackages/core-igp-0.3.4.tgz"
```

Commit both `Packages/manifest.json` and `Packages/packages-lock.json`. If the tarball is outside the project or source repository, other developers and clean CI agents must receive it at the same referenced path.

## Core Data Structures

The following types are in the `IGP.UnitySDK` or `IGP.UnitySDK.Models` namespaces. Properties with an `internal set` are returned by Core and are read-only to game code.

### Configuration and Runtime

| Type/field | Type | Meaning |
| --- | --- | --- |
| `IGPConfig.sdkEnvironment` | `IGPSDKEnvironment` | Environment used for Desktop and direct Core endpoints; normally `PROD`. |
| `IGPConfig.debugLogging` | `IGPLogLevel` | Diagnostic verbosity; use `Off` for production. |
| `IGPConfig.hostSessionPlatform` | `IGPHostSessionPlatform` | Selects the Core-owned `Desktop` or `Mobile` Host Session path; defaults to `Desktop`. Optional packages do not select this independently. |
| `IGPConfig.appId` | `int` | Required game application identifier. It is also used by Multiplayer, Compliance, and GameKit requests. |
| `IGPConfig.showAuthorizationFailureFallback`, `authorizationFailureFallbackTitle`, `authorizationFailureFallbackMessage`, `authorizationFailureFallbackHint`, `authorizationFailureFallbackButtonText`, `authorizationFailureFallbackQuitButtonText` | `bool`/`string` | Optional authorization failure UI values consumed by Core's host integration. |
| `IGPConfig.curioApiBaseUrlDebugOverride` | `string` | DEV-only direct Curio URL override. Leave empty in normal projects; PROD/PREVIEW ignore it. |
| `IGPConfig.desktopSessionAutoAttach` | hidden `bool` | Historical field name; controls automatic attach for the selected Desktop or Mobile Host Session. |
| `IGPConfig.desktopPipeEndpoint`, `desktopExecutablePathDebugOverride`, `desktopLaunchCommand` | hidden `string` | Desktop-only integration values. Leave them at their serialized defaults unless a documented Desktop integration explicitly supplies them. |
| `IGPRuntimeManager.Config` | `IGPConfig?` | The explicitly assigned config asset. |
| `IGPRuntimeManager.Host`, `IIGPRuntimeContext.Host` | `IIGPHostCommandGateway` | Shared Host Session command gateway for Core and optional packages; Core selects Desktop or Mobile internally. |
| `IGPRuntimeManager.RuntimeInfo.SaveRootPath` | `string` | Host-provided save location, or an empty string when unavailable. Reading it has no filesystem side effect. |
| `IGPRuntimeManager.IsInitialized` | `bool` | Whether normal Core/runtime initialization completed. Account calls can work before this is true. |
| `IGPRuntimeManager.HasUserSession` | `bool` | Whether Core currently holds a usable direct account session. Desktop login alone does not set this value. |

Create and assign one `IGPConfig` asset explicitly:

```csharp
var profile = await runtime.GetCurrentUserProfileAsync();
// runtime.Config.appId is the app identity used by Core and dependent packages.
```

### Account and Profile Results

| Type | Public fields/properties | Meaning |
| --- | --- | --- |
| `IGPPhoneCodeSendResult` | `Succeeded`, `DevelopmentCode`, `IsTestAccount` | Result of sending the phone sign-in code. `DevelopmentCode` is only populated by the configured development/test path. |
| `IGPUserSession` | `Profile` | Successful explicit sign-in or refresh result. Access and refresh tokens are never exposed. |
| `IGPUserProfile` | `Id`, `Nickname`, `Discriminator`, `DisplayTag`, `AvatarUrl`, `AvatarFrameUrl` | Current user's stable identity and display assets. URLs may be empty when the service has no asset. |
| `IGPPlayerProfileSummary` | `Id`, `Nickname`, `AvatarUrl`, `AvatarFrameUrl` | Lightweight profile returned by a batch lookup. |
| `IGPRuntimeManager.CurrentUserProfile` | `IGPUserProfile?` | Cached current profile, or `null` before a provider has supplied one. |

The normal account flow is:

```csharp
using System.Collections.Generic;
using IGP.UnitySDK.Models;

var sent = await runtime.SendPhoneSignInCodeAsync(phone);
var session = await runtime.SignInWithPhoneCodeAsync(phone, code, inviteCode);
IGPUserProfile current = session.Profile;
IReadOnlyList<IGPPlayerProfileSummary> players =
    await runtime.GetPlayerProfilesAsync(playerIds);
```

`SignInWithPhoneCodeAsync` logs in an existing account or creates the missing account after the SMS challenge. `RefreshUserSessionAsync` refreshes the in-memory session; `SignOut` clears only that direct Core session. These methods do not require `InitializeAsync`. If Desktop is attached and has a valid user context, profile lookup may use Desktop; otherwise Core uses its direct session. A failed Desktop call is not replayed through another provider.

### Error and Lifetime Rules

- Core methods throw `IGPSDKException` or a capability-specific exception with a stable `Code`; callers should branch on the code rather than localized message text.
- Direct authenticated requests refresh once after a `401` and retry once. A failed refresh or second `401` clears the direct session.
- Access and refresh credentials remain in memory and are redacted from logs and `ToString()` output.
- Destroying the `IGPRuntimeManager` cancels new and in-flight calls through its lifetime token.

See [ACCOUNT-AND-PROFILES.md](ACCOUNT-AND-PROFILES.md) for validation limits and provider selection details.

## Migrate From `.unitypackage`

Do not keep the legacy `Assets/IGP.UnitySDK` directory and this UPM package installed at the same time. The two carriers contain the same module and can create duplicate assemblies.

Before switching:

1. Back up user-owned `IGPConfig` assets, modified samples, and custom scripts.
2. Remove the legacy `Assets/IGP.UnitySDK` directory and install the UPM tarball at the same SDK version.
3. If an existing `IGPConfig.asset` shows `Missing (Mono Script)`, it was serialized against the source package's `IGPConfig.cs` `MonoScript`. Changing the asset `.meta` GUID or editing the package cache cannot repair that reference. Recreate a new `IGPConfig` through `Assets > Create > IGP > Config`, re-enter the values (especially `appId`), assign it to `IGPRuntimeManager`, and verify the scene/prefab. Keep the source `.unitypackage` instead when preserving the original serialized asset is required.
4. Confirm scenes and prefabs have no missing script references before upgrading the SDK version.

Create and bind configuration assets explicitly. The package does not scan or modify the consuming project's assets, scenes, prefabs, or project settings.
