> For the complete documentation index, see [llms.txt](/llms.txt)


# 1. Create an account and log in

Create a player account and use the saved credentials to log in again.



Start by making it possible to log in to the game. Display the logged-in player’s ID, and make sure you can return to the same account after stopping Play Mode in Unity.

On the first run, create an account and save its player ID and password. On later runs, log in with those saved credentials. The access token returned after login expires, so log in again each time the app starts.

## 1. Create a place to store player accounts

GS2 uses *namespaces* to keep settings and data separate. Create a GS2-Account namespace to store player accounts.


**Studio**

### Add Account Transfer

Open your `Adventure` project in Studio. Click **Add features** on the left and search for `Account Transfer`. If you cannot see this menu, select **Simple** at the top right.

Click **Add** on the **Account Transfer** card. This package also includes the Account settings used to store player accounts.

<a href="/images/adventure/studio-2026-11-3/identity-search.jpg" target="_blank" rel="noopener" aria-label="Search for Account Transfer under Add features, then click Add (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-search.jpg" alt="Search for Account Transfer under Add features, then click Add" loading="lazy"></a>

When the card says **Added**, Studio has finished loading the package.

<a href="/images/adventure/studio-2026-11-3/identity-added.jpg" target="_blank" rel="noopener" aria-label="The Account Transfer card marked Added (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-added.jpg" alt="The Account Transfer card marked Added" loading="lazy"></a>

### Deploy to GS2

Send the settings to GS2 so it can store player accounts. This is called *deployment*.

Click **Publish** on the left, then **Calculate server differences** in the **Deploy to the server** panel.

<a href="/images/adventure/studio-2026-11-3/identity-publish.jpg" target="_blank" rel="noopener" aria-label="Open Calculate server differences in the Deploy to the server panel (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-publish.jpg" alt="Open Calculate server differences in the Deploy to the server panel" loading="lazy"></a>

If **GS2 Login** opens, sign in with the email address and password of the developer account you created during setup.

<a href="/images/adventure/studio-2026-11-3/identity-gs2-login.jpg" target="_blank" rel="noopener" aria-label="Sign in with your GS2 developer account (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-gs2-login.jpg" alt="Sign in with your GS2 developer account" loading="lazy"></a>

After signing in, check the deployment destination and changes.

1. In **Select GS2 Project**, select your learning project, `adventure`, and **Tokyo (ap-northeast-1)**, then click **Select**.
2. In **Review changes to GS2**, review the changes for the `foundation-core-identity` package. In a new project, this creates a namespace named `Account`. Use the stack name supplied by Studio.
3. Click **Deploy 1 package** and wait for it to finish.
4. Return to **Publish** and check that the **Deploy to the server** panel says **Up to date**.

The `Account` namespace is now ready to store player accounts.


**SDK (Unity)**

### Create Account settings from the console

In the SDK course, use a template to create a namespace named `adventure-account`.

1. In the management console, open the **Tokyo region** of your learning project.
2. Select **Deploy → Stack list → Create stack**.
3. Download the template below. Set the stack name to `adventure-login` and select the downloaded `01-account.yaml` under **Template data**.
4. Click **Create** and wait until the execution status is **Create complete**.

```yaml
GS2TemplateFormatVersion: "2019-05-01"
Description: Adventure tutorial - player accounts
Resources:
  AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: adventure-account
Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
```

<a href="/samples/adventure/en/01-account.yaml" download>Download this template</a>




## 2. Add login to Unity


**Studio**

### Add the SDK and generated code to Unity

Export the files needed to use Account Transfer from Unity. This adds the SDK for communicating with GS2, GS2-Bind with its login components, and C# code for calling the features you selected.

Keep the Studio `Adventure` project and the Unity project from the setup page open. Stop Play Mode in Unity and save the `Adventure` scene.

#### 1. Select the destination Unity project

Click **Publish** on the left. In the **Update the Unity project** panel, click **Select and update Unity project**.

<a href="/images/adventure/studio-2026-11-3/identity-publish.jpg" target="_blank" rel="noopener" aria-label="Select a Unity project from the Update the Unity project panel on the Publish screen (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-publish.jpg" alt="Select a Unity project from the Update the Unity project panel on the Publish screen" loading="lazy"></a>

A folder picker opens. Select the **folder containing `Assets`, `Packages`, and `ProjectSettings`**. If your Unity project is named `AdventureUnity`, select `AdventureUnity` in the example below.

```text
AdventureUnity/           ← Select this folder
├── Assets/
├── Packages/
└── ProjectSettings/
```

Selecting the `Assets` folder or the folder containing your Studio project will not work; neither is the Unity project root.

After you select the folder, a confirmation screen opens. Check that **Destination** is your Unity project, then click **Update**. The destination shown in the screenshot is an example used for these screenshots.

<a href="/images/adventure/studio-2026-11-3/identity-unity-confirm.jpg" target="_blank" rel="noopener" aria-label="Check the destination and SDK packages, then click Update at the bottom right (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-unity-confirm.jpg" alt="Check the destination and SDK packages, then click Update at the bottom right" loading="lazy"></a>

This writes C# code to `Assets/GS2Studio/Generated` and adds the SDKs and GS2-Bind to Unity’s package settings. The contents of `Generated` are replaced on each update, so keep your own scripts outside that folder.

#### 2. Check that Studio finished exporting

When the update finishes, check the **Update the Unity project** panel:

- The status is **Up to date**.
- **Unity project** at the bottom shows the folder you selected.
- **Generated output** is `Assets/GS2Studio/Generated`.

<a href="/images/adventure/studio-2026-11-3/identity-unity-updated.jpg" target="_blank" rel="noopener" aria-label="Export complete: Up to date is shown, with the Unity project and generated output paths below (open full size in a new tab)"><img src="/images/adventure/studio-2026-11-3/identity-unity-updated.jpg" alt="Export complete: Up to date is shown, with the Unity project and generated output paths below" loading="lazy"></a>

Once linked, the button changes to **Update linked Unity project**. Use it for later exports. To change the destination, click **Change and update** to the right of the folder path.

#### 3. Check the imported files in Unity

1. Return to Unity Editor. Wait for the required packages to download and the C# code to compile.
2. In the **Project** window, open **Assets → GS2Studio → Generated** and check for C# files. If the Project window is hidden, open it with **Window → General → Project**.
3. Open **Window → Package Manager** and search for `GS2` in the installed packages. Check for `io.gs2.bind`, `io.gs2.csharp.sdk`, and `io.gs2.unity.sdk`. Select each package to see its ID in the details panel.
4. Open **Window → General → Console** and check that there are no red compilation errors.

If a package download fails, check the error in Package Manager and your network connection. For C# errors, select the red entry in the Console to read the details.

### Create the connection settings

Right-click in Unity’s Project window and select **Create → Game Server Services → Core → Environment**. Name the asset `AdventureEnvironment` and configure it in the Inspector as follows.

| Field | Value |
| --- | --- |
| Name | `adventure` |
| Region | `ApNortheast1` |
| Client Id | `ApplicationClientId` from `Default` |
| Client Secret | `ApplicationClientSecret` from `Default` |

The credentials are blank in the screenshot. In your project, enter the values listed above.

<a href="/images/adventure/unity-6000-3/environment.jpg" target="_blank" rel="noopener" aria-label="AdventureEnvironment in the Inspector: Name is adventure and Region is Ap Northeast 1 (open full size in a new tab)"><img src="/images/adventure/unity-6000-3/environment.jpg" alt="AdventureEnvironment in the Inspector: Name is adventure and Region is Ap Northeast 1" loading="lazy"></a>

In the scene, select **GameObject → Create Empty** and name it `Gs2`. Use **Add Component** in the Inspector to add the following components.

| Component | Settings |
| --- | --- |
| `GS2/Core/Gs2ClientHolder` | Add `AdventureEnvironment` as one entry in Environments. Set Active Environment Name to `adventure`. |
| `GS2/Core/Gs2GameSessionHolder` | Use the default settings. |
| `GS2/Account/AutoLogin` | Set Account Namespace to `Account` and enable Persist Account. |
| `GS2/Account/PlayerPrefs Account Store` | Set Key Prefix to `adventure.main`. |
| `GS2 Studio/Runtime/Gs2HolderRuntimeContextProvider` | Assign the components above to Client Holder and Session Holder. |

The **Name** field in `Environment` must match **Active Environment Name** in Client Holder. Renaming the asset file alone does not set this value.

<a href="/images/adventure/unity-6000-3/client-holder.jpg" target="_blank" rel="noopener" aria-label="Assign AdventureEnvironment to the Client Holder’s Environments in the Gs2 Inspector (open full size in a new tab)"><img src="/images/adventure/unity-6000-3/client-holder.jpg" alt="Assign AdventureEnvironment to the Client Holder’s Environments in the Gs2 Inspector" loading="lazy"></a>

### Connect the events that save and restore the account

Click **+** in AutoLogin’s events and assign the same `Gs2` object. When choosing a function, select the **Dynamic** entry that accepts arguments.

| AutoLogin event | Function to connect |
| --- | --- |
| On Account Created | `Gs2PlayerPrefsAccountStore.Remember` (Dynamic string, string) |
| On Restore Account | `Gs2PlayerPrefsAccountStore.Restore` (Dynamic Gs2AutoLoginAction) |

Enable Persist Account and connect both events. These connections save the account credentials when the account is created and load them the next time you enter Play Mode.

### Display the player ID

Connect a Unity text component to **Player ID Label** to display the logged-in player’s ID.

#### 1. Create the text object

1. Select **GameObject → UI (Canvas) → Text - TextMeshPro** and name it `PlayerIdText`. Unity also creates a Canvas if there isn’t one yet.
2. If **TMP Importer** opens, click **Import TMP Essentials**.
3. To use the font shown in the examples, open the <a href="https://github.com/notofonts/noto-cjk/blob/main/Sans/SubsetOTF/JP/NotoSansJP-Regular.otf" target="_blank" rel="noopener">Noto Sans JP font file (new tab)</a> and click **Download raw file**. Create `Assets/Fonts` in Unity’s Project window and drag `NotoSansJP-Regular.otf` into it.
4. Select the font and choose **Assets → Create → TextMeshPro → Font Asset → SDF**. Name the Font Asset `AdventureFont` and set **Atlas Population Mode** to **Dynamic** in the Inspector.
5. Select `PlayerIdText` in the Hierarchy and assign `AdventureFont` to TextMeshPro’s **Font Asset**.
6. Adjust its position and width in Rect Transform so it appears near the top of the screen. Make it wide enough to show a long player ID.
7. Clear TextMeshPro’s **Text Input**. The component supplies the text after login.

<a href="/images/adventure/unity-6000-3/text-font.jpg" target="_blank" rel="noopener" aria-label="PlayerIdText with AdventureFont assigned and Text Input left empty (open full size in a new tab)"><img src="/images/adventure/unity-6000-3/text-font.jpg" alt="PlayerIdText with AdventureFont assigned and Text Input left empty" loading="lazy"></a>

#### 2. Connect Player ID Label

With `PlayerIdText` selected, choose **Add Component → GS2 → Core → Player ID Label** in the Inspector.

| Field | Settings |
| --- | --- |
| Session Holder | Drag in `Gs2` from the Hierarchy. |
| Format | `Player ID: {userId}` |

Click **+** under **On Update** and assign `PlayerIdText` itself. Choose **TextMeshProUGUI → Dynamic string → text**. Use the Dynamic string entry that displays the received string, rather than an entry with a fixed text input.

<a href="/images/adventure/unity-6000-3/player-id-label.jpg" target="_blank" rel="noopener" aria-label="Player ID Label: Session Holder is Gs2, and On Update calls PlayerIdText’s TextMeshProUGUI.text (open full size in a new tab)"><img src="/images/adventure/unity-6000-3/player-id-label.jpg" alt="Player ID Label: Session Holder is Gs2, and On Update calls PlayerIdText’s TextMeshProUGUI.text" loading="lazy"></a>

The ID now appears after a successful login. It also updates to the current ID when you log in with the saved account or enable this text after login.

### Show login status and errors

Add a separate text object to show the login status.

1. Create another **Text - TextMeshPro** under the Canvas. Name it `LoginStatus` and place it below `PlayerIdText`.
2. Assign `AdventureFont` to **Font Asset** and enter `Logging in…` in **Text Input**.
3. In AutoLogin on `Gs2`, click **+** under **On Auto Login Complete** and assign `LoginStatus`. Select the **TextMeshProUGUI → text** entry with a fixed string input and leave that input empty. This clears the status text after login.
4. Assign `LoginStatus` to **On Error** on both Client Holder and AutoLogin. Select the **TextMeshProUGUI → text** entry with a fixed string and enter `Login failed. Check the settings and connection.` Do not use the Dynamic entry for these events.

<a href="/images/adventure/unity-6000-3/login-events.jpg" target="_blank" rel="noopener" aria-label="AutoLogin events: Remember and Restore save and restore the account, and completion clears LoginStatus. Key Prefix is adventure.main (open full size in a new tab)"><img src="/images/adventure/unity-6000-3/login-events.jpg" alt="AutoLogin events: Remember and Restore save and restore the account, and completion clears LoginStatus. Key Prefix is adventure.main" loading="lazy"></a>

Save the scene and enter Play Mode. Login is working if the status message disappears and the player ID appears.


**SDK (Unity)**

### Attach the login script

Use UniTask to await the SDK’s asynchronous operations. Code after `await` runs once the request completes; `catch` handles errors.

1. Create `Assets/AdventureLogin.cs` and paste in the code below.
2. Create an empty GameObject in the scene and name it `Adventure`.
3. Add `AdventureLogin` and set Client Id and Client Secret in the Inspector to the outputs from `Default`.
4. Set Account Namespace to `adventure-account` and Account Slot to `main`.
5. Enter Play Mode. Click **Log in** at the top left and check that the player ID appears.

```csharp
using Cysharp.Threading.Tasks;
using Gs2.Core.Model;
using Gs2.Unity.Core;
using Gs2.Unity.Util;
using UnityEngine;

public sealed class AdventureLogin : MonoBehaviour
{
    [SerializeField] private string clientId = "YOUR_CLIENT_ID";
    [SerializeField] private string clientSecret = "YOUR_CLIENT_SECRET";
    [SerializeField] private string accountNamespace = "adventure-account";
    [SerializeField] private string accountSlot = "main";

    public Gs2Domain Gs2 { get; private set; }
    public GameSession Session { get; private set; }
    private bool busy;
    private string message = "Please log in";
    private string SaveKey => $"adventure.{clientId}.{accountNamespace}.{accountSlot}";

    private void OnGUI()
    {
        GUILayout.BeginArea(new Rect(20, 20, 650, 170), GUI.skin.box);
        GUILayout.Label(message);
        GUI.enabled = !busy && Session == null;
        GUILayout.Label("Account slot (main / practice, etc.)");
        accountSlot = GUILayout.TextField(accountSlot);
        if (GUILayout.Button("Log in")) Login().Forget();
        GUI.enabled = true;
        GUILayout.EndArea();
    }

    private async UniTask Login()
    {
        busy = true;
        message = "Logging in...";
        try
        {
            if (Gs2 == null)
            {
                Gs2 = await Gs2Client.CreateAsync(
                    new BasicGs2Credential(clientId, clientSecret), Region.ApNortheast1);
            }

            var userId = PlayerPrefs.GetString(SaveKey + ".userId", "");
            var password = PlayerPrefs.GetString(SaveKey + ".password", "");
            if (string.IsNullOrEmpty(userId) != string.IsNullOrEmpty(password))
            {
                message = "Saved credentials are incomplete. Check the account slot.";
                return;
            }
            if (string.IsNullOrEmpty(userId))
            {
                var create = await Gs2.Account.Namespace(accountNamespace).CreateAsync();
                var model = await create.ModelAsync();
                userId = model.UserId;
                password = model.Password;
                PlayerPrefs.SetString(SaveKey + ".userId", userId);
                PlayerPrefs.SetString(SaveKey + ".password", password);
                PlayerPrefs.Save();
            }

            var login = await Gs2.LoginAsync(
                new Gs2AccountAuthenticator(new AccountSetting
                {
                    accountNamespaceName = accountNamespace,
                    keyId = "grn:gs2:{region}:{ownerId}:key:default:key:default"
                }), userId, password);
            Session = login;
            message = "Logged in. Player ID: " + Session.AccessToken.UserId;
        }
        catch (System.Exception error) { message = "Could not connect: " + error.GetType().Name; }
        finally { busy = false; }
    }
}
```

<a href="/samples/adventure/en/AdventureLogin.cs" download>Download AdventureLogin.cs</a>

The `{region}` and `{ownerId}` placeholders in `AccountSetting.keyId` identify the default key and are resolved by GS2. Leave them as written. Both the key namespace and key name are `default`.

The code saves a new account’s credentials before login. If the login request fails, the next click retries with the same account. Failure to log in with saved credentials does not create a different account automatically.




This tutorial stores credentials locally with `PlayerPrefs`. It is not encrypted, so choose an appropriate storage method for a released game. Keep player passwords and Client Secrets out of screens, logs, and public repositories.

## 3. Log in again with the same account

Stop Play Mode, then start again and log in. If the player ID is unchanged, the saved account was restored successfully.

| Action | Expected result |
| --- | --- |
| Log in for the first time | A player ID appears. |
| Stop Play Mode, start again, and log in | The same ID appears. |
| Stop Play Mode, disconnect the network, then start again and log in | An error message appears. |
| Restore the network, stop and restart Play Mode, then log in | Login succeeds with the saved account. |

Studio logs in automatically when Play Mode starts. With the SDK, click the login button. Saved credentials remain after Play Mode stops.

## Practice: create a second player

In Studio, stop Play Mode, change **Key Prefix** in PlayerPrefs Account Store to `adventure.practice`, then start again. With the SDK, stop Play Mode, change **Account Slot** in the `AdventureLogin` Inspector to `practice`, start again, and log in. Is the player ID different now?

When finished, stop Play Mode. Restore Studio’s Key Prefix to **`adventure.main`**, or the SDK’s Account Slot to **`main`**, then start again and log in. Check that the original player ID returns.

[Next: Add a quest and display the quest list]()



