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

# 実装

アカウント発行〜ログインまでを実装してみましょう




ここでは、GS2 SDK を使用してアカウントの作成とログインを行う最小限の実装方法を解説します。

各プラットフォームごとの完全なコードは [サンプルコード全文]() をご確認ください。

**Unity での実装について**

Unity SDK では非同期処理に Coroutine を使用しています。以下のコード例は Coroutine 内（`IEnumerator` を返すメソッド内）で実行することを想定しています。

## GS2 SDKの初期化



**Unity**
```csharp

    // Setup variables

    var clientId = "YourClientId";
    var clientSecret = "YourClientSecret";
    var accountNamespaceName = "game-0001";

    // Setup general setting
    Gs2Domain gs2;
    {
        var future = Gs2Client.CreateFuture(
            new BasicGs2Credential(
                clientId,
                clientSecret
            ),
            Region.ApNortheast1
        );
        yield return future;
        if (future.Error != null) {
            throw future.Error;
        }
        gs2 = future.Result;
    }
```
**Unreal Engine**
```cpp

	// Setup variables

	const auto ClientId = "YourClientId";
	const auto ClientSecret = "YourClientSecret";
	const auto AccountNamespaceName = "game-0001";

    // Create GS2 client

    const auto InitializeFuture = Gs2::UE5::Core::FGs2Client::Create(
        MakeShared<Gs2::Core::Model::FBasicGs2Credential>(
            ClientId,
            ClientSecret
        ),
        Gs2::Core::Model::ApNorthEast1
    );
    InitializeFuture->StartSynchronousTask();
    if (InitializeFuture->GetTask().IsError())
    {
        UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(InitializeFuture->GetTask().Error()->String()));
        return InitializeFuture->GetTask().Error();
    }
    const auto Gs2 = InitializeFuture->GetTask().Result();
```
**Godot**
```gdscript

    # Setup variables

    var client_id = "YourClientId"
    var client_secret = "YourClientSecret"
    var account_namespace_name = "game-0001"
    var account_encryption_key_id = "grn:gs2:{region}:{ownerId}:key:account-encryption-key-namespace:key:account-encryption-key"

    # Initialize GS2 SDK

    var credential = Gs2BasicCredential.new(client_id, client_secret)
    var connection = Gs2Connection.new(credential, Gs2Region.AP_NORTHEAST_1)
    var ez = Gs2EzDomain.new(connection)
```


### Setup variables

まずは4つの変数を定義しています。

| 変数名 | 用途 | 取得元 |
| ----- | --- | ----- |
| clientId | GS2にアクセスするための認証情報 | [クレデンシャル(APIキー)の作成]() で作成した値 |
| clientSecret | GS2にアクセスするための認証情報 | [クレデンシャル(APIキー)の作成]() で作成した値 |
| accountNamespaceName | 利用する GS2-Account のネームスペース名 | [ログイン処理に必要なリソースを準備]() で作成した値 |
| accountEncryptionKeyId | アカウント認証に使用する暗号鍵の GRN | [ログイン処理に必要なリソースを準備]() で作成したスタックの `KeyAccountAuthenticationKeyId` 出力値 |

### Setup general setting

Gs2Client.CreateFuture(UniTask 使用時は Gs2Client.CreateAsync) で GS2 のクライアントを作成します。
`clientId` や `clientSecret` が不適切な場合、ここでエラーが返ります。
Godot では `Gs2Connection` を作成し、ゲームエンジン向けの Ez レイヤーを利用するために `Gs2EzDomain` を初期化します。各サービスには `ez.account` や `ez.inventory` のようなサービスプロパティからアクセスします。

## 匿名アカウントの新規作成



**Unity**
```csharp

    // define GS2-Account namespace
    var gs2Account = gs2.Account.Namespace(
        accountNamespaceName
    );

    // Create an anonymous account
    EzAccount account;
    {
        Debug.Log("Create an anonymous account");
        var future = gs2Account.CreateFuture();
        yield return future;
        if (future.Error != null) {
            throw future.Error;
        }
        var future2 = future.Result.ModelFuture();
        yield return future2;
        if (future2.Error != null) {
            throw future2.Error;
        }
        account = future2.Result;
    }
```
**Unreal Engine**
```cpp

	// Create an anonymous account

    UE_LOG(GameLog, Display, TEXT("Create anonymous account"));

    const auto CreateFuture = Gs2->Account->Namespace(
        AccountNamespaceName
    )->Create();
    CreateFuture->StartSynchronousTask();
    if (CreateFuture->GetTask().IsError())
    {
        UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(CreateFuture->GetTask().Error()->String()));
        return CreateFuture->GetTask().Error();
    }

	// Load created account

    const auto LoadFuture = CreateFuture->GetTask().Result()->Model();
    LoadFuture->StartSynchronousTask();
    if (LoadFuture->GetTask().IsError())
    {
        UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(LoadFuture->GetTask().Error()->String()));
        return LoadFuture->GetTask().Error();
    }
    const auto Account = LoadFuture->GetTask().Result();

    // Dump anonymous account

    UE_LOG(GameLog, Display, TEXT("UserId: %s"), ToCStr(*Account->GetUserId()));
    UE_LOG(GameLog, Display, TEXT("Password: %s"), ToCStr(*Account->GetPassword()));
```
**Godot**
```gdscript

    # Define the GS2-Account namespace
    var gs2_account = ez.account.namespace_(
        account_namespace_name
    )

    # Create an anonymous account
    var create_result = await gs2_account.create()
    if create_result.error != null:
        push_error(str(create_result.error))
        return

    var model_result = await create_result.result.model()
    if model_result.error != null:
        push_error(str(model_result.error))
        return

    var account = model_result.result
    print("UserId: ", account.user_id)
    print("Password: ", account.password)
```


ここではゲームプレイヤーを識別するためのアカウントの作成を行っています。
accountNamespaceName にはアカウントを追加する先のネームスペース名を指定します。

なお、このサンプルでは毎起動時に新規のアカウントでログインする挙動になっていますが、通常は、アカウントの作成はアプリケーションの初回起動時にのみ行ないます。
実際のアプリケーションではこの応答のアカウント情報をローカルストレージ等に保存し、2回目以降はローカルストレージ等から取得した作成済みのアカウント情報で、既存のゲームプレイヤーとしてログインを行います。

## ログイン処理



**Unity**
```csharp

    // Log-in created anonymous account
    GameSession gameSession;
    {
        var future = gs2.LoginFuture(
            new Gs2AccountAuthenticator(
                accountSetting: new AccountSetting {
                    accountNamespaceName = accountNamespaceName,
                }
            ),
            account.UserId,
            account.Password
        );
        yield return future;
        if (future.Error != null) {
            throw future.Error;
        }
        gameSession = future.Result;
    }
```
**Unreal Engine**
```cpp

    // Log-in created anonymous account

    const auto LoginFuture = Gs2->Login(
        MakeShareable<Gs2::UE5::Util::IAuthenticator>(
            new Gs2::UE5::Util::FGs2AccountAuthenticator(
                MakeShared<Gs2::UE5::Util::FAccountSetting>(
                    AccountNamespaceName
                )
            )
        ),
        *Account->GetUserId(),
        *Account->GetPassword()
    );
    LoginFuture->StartSynchronousTask();
    if (LoginFuture->GetTask().IsError())
    {
        UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(LoginFuture->GetTask().Error()->String()));
        return LoginFuture->GetTask().Error();
    }
    const auto GameSession = LoginFuture->GetTask().Result();
```
**Godot**
```gdscript

    # Log in with the created anonymous account
    var authenticator = Gs2AccountAuthenticator.new(
        account_namespace_name,
        account_encryption_key_id
    )
    var game_session = Gs2GameSession.new(
        authenticator,
        connection,
        account.user_id,
        account.password
    )
    var login_result = await game_session.login()
    if login_result.error != null:
        push_error(str(login_result.error))
        return
```


つづいて GS2 へのログイン処理です。
Gs2AccountAuthenticator にアカウントの認証に関する情報を指定します。具体的にはログインに使用する GS2-Account のネームスペース名を指定しています。
Godot では、あわせてアカウント認証に使用する暗号鍵の GRN を指定します。
更に、 userId password には作成したアカウントのユーザIDとパスワードを指定します。

結果として GameSession オブジェクトが返ります。
以降 GS2 の API を呼び出すときにログイン状態でなければ呼び出せないAPIの引数には GameSession を渡して使用することとなります。

## ログイン後呼び出し可能なAPIの呼び出し



**Unity**
```csharp

    // Load TakeOver settings
    {
        var it = gs2Account.Me(
            gameSession
        ).TakeOvers();
        while (it.HasNext()) {
            yield return it.Next();
            if (it.Error != null)
            {
                throw it.Error;
            }
            if (it.Current != null)
            {
                Debug.Log($"Type: {it.Current.Type}");
                Debug.Log($"Identifier: {it.Current.UserIdentifier}");
            }
        }
    }
```
**Unreal Engine**
```cpp

	// Load TakeOver settings

	const auto It = Gs2->Account->Namespace(
		AccountNamespaceName
	)->Me(
		GameSession
	)->TakeOvers();
	for (const auto TakeOver : *It)
	{
		UE_LOG(GameLog, Display, TEXT("Type: %s"), *TakeOver->GetType());
		UE_LOG(GameLog, Display, TEXT("Identifier: %s"), *TakeOver->GetUserIdentifier());
	}
```
**Godot**
```gdscript

    # Load TakeOver settings
    var load_result = await gs2_account.me(
        game_session
    ).take_overs().load()
    if load_result.error != null:
        push_error(str(load_result.error))
        return

    for take_over in load_result.result:
        print("Type: ", take_over.type)
        print("Identifier: ", take_over.user_identifier)
```


ログイン状態でなければ使用できないAPIの一例として、引き継ぎ設定の一覧を取得するAPIを呼び出しています。
GameSession を渡して、ログイン中のゲームプレイヤーに設定されている引き継ぎ設定の一覧を取得できます。

### GS2 SDKの終了処理



**Unity**
```csharp

    // Finalize GS2-SDK
    {
        var future = gs2.DisconnectFuture();
        yield return future;
        if (future.Error != null) {
            throw future.Error;
        }
    }
```
**Unreal Engine**
```cpp

	// Finalize GS2-SDK

    const auto FinalizeFuture = Gs2->Disconnect();
    FinalizeFuture->StartSynchronousTask();
    if (FinalizeFuture->GetTask().IsError())
    {
        UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(FinalizeFuture->GetTask().Error()->String()));
        return FinalizeFuture->GetTask().Error();
    }
```
**Godot**
```gdscript

    # Finalize GS2 SDK
    connection.disconnect_session()
```


GS2との接続を終了します。

## チュートリアルはおえましたか？

[GS2 の使い方についてガイダンスしている YouTube チャンネル をご確認ください！]()

[より実践的なサンプルも提供しています。]()

[GS2 を使えば他にどんなことが実現できるのか調べましょう]()

[GS2 を使用した開発ワークフローについて学びましょう]()




- [サンプルコード全文](/ja/get_start/tutorial/coding/all/)
  
