Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 81 additions & 139 deletions skills/build-live-game/SKILL.md

Large diffs are not rendered by default.

286 changes: 132 additions & 154 deletions skills/build-live-game/references/achievements.md

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions skills/build-live-game/references/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Used for backend tooling, editor extensions, Deployment Window integrations, and
```csharp
using Unity.Services.Apis;

var adminClient = UnityServicesApiClient.AdminClient;
var adminClient = ApiService.CreateAdminClient();
adminClient.SetServiceAccount(keyId, keySecret);
```

Expand Down Expand Up @@ -135,7 +135,7 @@ Same pattern for **Private Custom** (`GetPrivateCustomItems`, `SetPrivateCustomI

## IGameClient

Created via `UnityServicesApiClient.GameClient` after player authentication. Runtime only.
Created via `ApiService.CreateGameClient()` after player authentication. Runtime only.

| Property | Type | Service |
|---|---|---|
Expand All @@ -162,7 +162,7 @@ Most developers use the high-level SDKs (`CloudSaveService.Instance`, `Leaderboa
Used from dedicated game servers. Authenticated with a server key or service account.

```csharp
var serverClient = UnityServicesApiClient.ServerClient;
var serverClient = ApiService.CreateServerClient();
await serverClient.SignInFromServer();
```

Expand All @@ -182,7 +182,7 @@ await serverClient.SignInFromServer();
Elevated server client with admin-equivalent access to player data. Use when a dedicated server needs to read or modify any player's data with elevated privileges.

```csharp
var trustedClient = UnityServicesApiClient.TrustedClient;
var trustedClient = ApiService.CreateTrustedClient();
trustedClient.SetServiceAccount(keyId, keySecret);
await trustedClient.SignInWithServiceAccount(projectId, environmentId);
```
Expand All @@ -199,7 +199,7 @@ Same service area properties as `IServerClient`, plus `PlayerAuthentication` and
using Unity.Services.Apis;

// Admin client is editor-only. Guard with #if UNITY_EDITOR in runtime assemblies.
var adminClient = UnityServicesApiClient.AdminClient;
var adminClient = ApiService.CreateAdminClient();
adminClient.SetServiceAccount("your-key-id", "your-key-secret");
```

Expand All @@ -211,7 +211,7 @@ This is the pattern for Deployment Window integrations that push JSON into Cloud
using Unity.Services.Apis;
using Unity.Services.Apis.Admin.CloudSave;

var adminClient = UnityServicesApiClient.AdminClient;
var adminClient = ApiService.CreateAdminClient();
adminClient.SetServiceAccount(keyId, keySecret);

string projectId = CloudProjectSettings.projectId;
Expand Down Expand Up @@ -253,7 +253,7 @@ async Task SetupGameClient()
await AuthenticationService.Instance.SignInAnonymouslyAsync();

// Game client is automatically authenticated via the signed-in player
var client = UnityServicesApiClient.GameClient;
var client = ApiService.CreateGameClient();
var scores = await client.Leaderboards.GetScoresAsync("WEEKLY_LB");
}
```
Expand All @@ -264,7 +264,7 @@ async Task SetupGameClient()
using Unity.Services.Apis;

// serverAuthToken provided by the Multiplay server environment
var serverClient = UnityServicesApiClient.ServerClient;
var serverClient = ApiService.CreateServerClient();
await serverClient.SignInFromServer();

await serverClient.Lobby.CreateOrJoinLobbyAsync(...);
Expand Down
32 changes: 13 additions & 19 deletions skills/build-live-game/references/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,19 +404,19 @@ await AuthenticationService.Instance.DeleteAccountAsync();

Throws `AuthenticationException` (extends `RequestFailedException`) on failure. Use `ex.ErrorCode` and compare against `AuthenticationErrorCodes`:

| Constant | Value | Meaning |
|---|---|---|
| `ClientInvalidUserState` | 10000 | Operation not valid in current state |
| `ClientNoActiveSession` | 10001 | No active session |
| `InvalidParameters` | 10002 | Bad input parameters |
| `AccountAlreadyLinked` | 10003 | External ID already linked to another player |
| `AccountLinkLimitExceeded` | 10004 | Max linked accounts for this provider type |
| `ClientUnlinkExternalIdNotFound` | 10005 | External ID not linked |
| `ClientInvalidProfile` | 10006 | Invalid profile name |
| `InvalidSessionToken` | 10007 | Session token invalid or expired |
| `InvalidProvider` | 10008 | Unknown identity provider |
| `BannedUser` | 10009 | Player has been banned |
| `EnvironmentMismatch` | 10010 | Session token from a different environment |
| Constant | Value | Meaning | Fix |
|---|---|---| :-- |
| `ClientInvalidUserState` | 10000 | Operation not valid in current state | Check the player's sign-in state before the call; call `SignOut()` first when switching profile |
| `ClientNoActiveSession` | 10001 | No active session | Sign in before calling the operation |
| `InvalidParameters` | 10002 | Bad input parameters | Validate the input against the provider or username rules before the call |
| `AccountAlreadyLinked` | 10003 | External ID already linked to another player | Sign in with that identity, or link with `ForceLink` only after the player confirms |
| `AccountLinkLimitExceeded` | 10004 | Max linked accounts for this provider type | Unlink an existing identity of that provider type first |
| `ClientUnlinkExternalIdNotFound` | 10005 | External ID not linked | Check `PlayerInfo.Identities` before unlinking |
| `ClientInvalidProfile` | 10006 | Invalid profile name | Use a valid profile name |
| `InvalidSessionToken` | 10007 | Session token invalid or expired | Clear the token with `ClearSessionToken()` and sign in again only if the player has a linked identity; for an anonymous-only player keep the token, because clearing it permanently loses the account |
| `InvalidProvider` | 10008 | Unknown identity provider | Check the provider name matches the one configured in the Dashboard |
| `BannedUser` | 10009 | Player has been banned | Not retryable; the player cannot sign in |
| `EnvironmentMismatch` | 10010 | Session token from a different environment | Keep the token for its original environment and sign in to the other environment under a separate profile with `SwitchProfile`; clear the token only if the player has a linked identity |

**Error response format:** Authentication errors follow RFC 7807 (Problem Details). Branch your error handling on `status` and `title` fields, never on `detail` -- the detail message may change without notice.

Expand All @@ -429,9 +429,3 @@ Throws `AuthenticationException` (extends `RequestFailedException`) on failure.
**Anonymous-only accounts:** Calling `ClearSessionToken()` or `SignOut(clearCredentials: true)` on an account that ONLY has anonymous sign-in will **permanently lose** that account. Always link at least one external provider before clearing credentials.

**DeleteAccountAsync compliance:** iOS App Store (Guideline 5.1.1) requires apps that support account creation to offer account deletion. `DeleteAccountAsync()` only deletes **Authentication data**. It does NOT automatically clean up data in other UGS services (Cloud Save, Leaderboards, etc.). You must manually delete data from each service before calling `DeleteAccountAsync()`.

---

## Asset Store Building Blocks

- **Player Account Building Block:** Ready-made sign-in UI (anonymous, Unity browser, username/password), Cloud Save integration for player data, and a Cloud Code module for server-authoritative writes. [Asset Store](https://assetstore.unity.com/packages/essentials/tutorial-projects/unity-building-block-player-account-341928)
Loading
Loading