Game Server Services ことはじめ

# Game Server Services とは

Game Server Services(GS2) というサービスで、ゲームサーバのSaaSです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/4ade61b4-b1d2-5671-ca80-7077f5d63271.png)
https://gs2.io

# GS2 で出来ること

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/40c11d4b-f921-1b38-7e47-60c43c75f30a.png)

ゲームで必要とされるようなサーバ機能が一式用意されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/5ed54e87-0571-928e-17ff-dce7dfb54721.png)

Unity SDK をはじめとした、様々なプログラミング言語のSDKが提供されており、
サーバ機能ごとに直感的なAPIが用意されており、ゲーム内からは必要なタイミングで必要なAPIを呼び出すだけで使用できます。

# 利用料金

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/19a83bfb-3a02-aad0-46b2-f9ca432f604d.png)

## Individual

過去12か月間の売上高が1000万円未満であれば、無料で使用できます。
ただし、ゲームのタイトル画面にロゴを掲載する必要があります。

## Professional

APIを呼び出すたびに 0.02円 がかかります。
100万回呼び出して2万円ということになります。

## Enterprise

月間アクティブユーザ一人当たり30円～100円かかります。

# 登録方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/a585b48b-33f0-5d2a-dfe1-559a907e9035.png)

メールアドレスと名前、パスワードを入力すると登録できます。
その後メールアドレス宛に認証メールが届くのでURLをクリックすると登録が完了します。

# はじめかた

## プロジェクトの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/a29c637d-3357-3389-ab1d-2dd004f60591.png)

はじめにプロジェクトを作成する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/f2dee7ee-fcf8-2893-bc83-cfca714b45d3.png)

プロジェクトの名前と料金プランを選択します。
プロジェクトの名前には英数字しか使用できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/dbcdbabe-c691-0bf0-0852-be7ed8c3c083.png)

プロジェクトをが作成出来たら『管理メニューへ』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/d88d5bd9-1ed0-a061-a1fe-2ea1c2ad0995.png)

ダッシュボードが表示されます。
まずは『はじめかた』を見てみます。

## チュートリアル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/059d3c61-fbcf-fcd4-02ef-649adb92f0ed.png)

開発ドキュメントページに遷移して、チュートリアルが表示されます。
詳細はチュートリアルを読むとして、ざっくり手順を説明します。

### クレデンシャルの作成

クレデンシャルとは
> クレデンシャルとは、ネットワーク セキュリティの世界で使用された場合には、IDやパスワードをはじめとする、ユーザ等の認証に用いられる情報の総称を意味します。 「クレデンシャル情報」と言う場合もあります。 多くのシステムは、ユーザIDをパスワードを、クレデンシャルとして使用しています。
[クレデンシャル - F5 Networks](https://www.f5.com/ja_jp/services/resources/glossary/credential#:~:text=%E3%82%AF%E3%83%AC%E3%83%87%E3%83%B3%E3%82%B7%E3%83%A3%E3%83%AB%E3%81%A8%E3%81%AF%E3%80%81%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%20%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3,%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)

ようするに、ゲーム内からGS2にアクセスするためのAPIキーです。

GS2 では複数のクレデンシャルを作成できて、クレデンシャルごとに操作可能なAPIを設定できます。
これを使うと、ゲーム内から使用するクレデンシャルと、管理ツールから使用するクレデンシャルで出来ることを分けて、管理ツールはより強力な権限を持たせることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/3a088c8e-7b23-14da-a984-15c76866a911.png)

#### ユーザの作成

クレデンシャルは Identifier の管理画面から追加することができます。
まずはユーザを作成する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/df5b2647-23b9-a5f8-a924-b5911491096c.png)

InGame というユーザを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/4f697502-64f3-3292-c412-315d98e4fe30.png)

ユーザの作成ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/a9b9c59d-7b0e-25eb-e8b9-47fd24b7ceb1.png)

#### 権限の設定

セキュリティポリシーのタブでこのユーザで操作できる権限を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/38b7fc58-47e5-b559-c87a-b008276d401e.png)

セキュリティポリシーは自分で作成することもできますが、基本的な設定は最初から用意されています。
ApplicationAccess の『割り当て』を選択して割り当てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/ae9a9908-16de-a07a-058c-11b089ace98e.png)

これで、ゲーム内から使用するのに十分な権限のユーザが作成できました。

#### クレデンシャルを発行

続けて、このユーザ権限でゲーム内からAPIを呼び出すためのクレデンシャルを発行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/b12186b4-236b-9d17-01ea-fe195bbe659e.png)

クレデンシャルタブを選択して『クレデンシャルの新規作成』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/9644e4b8-65c1-ab66-3496-1dea6a6d1160.png)

InGame ユーザのクレデンシャルを発行するので、そのまま作成をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/da3d8f87-4cdb-7196-f6e3-f825ead83db0.png)

クライアントIDとクライアントシークレットが発行されました。
ゲーム内にはこの値を埋め込んで使用します。

#### GS2-Deploy を使ってみる

これまで管理画面でポチポチ登録していましたが、この手順を自動化できます。

#### テンプレートファイルの説明

自動化するためには、どういう設定が必要かをファイルに記述する必要があります。
このファイルをテンプレートと呼びます。

テンプレートを更新してアップロードすると、前回アップロード時との差分を検出して
増えている項目があれば『作成』
減っている項目があれば『削除』
変わっている項目があれば『変更』
してくれる仕組みが GS2-Deploy です。

これを使いこなせば、いちいち管理画面を触らなくていいだけでなく、
サーバの設定をバージョン管理したり、異なるGS2アカウントやプロジェクトに環境を再構築できます。

```yaml
GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10

Globals:
  Alias:
    ApplicationUserName: InGame

Resources:
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}

  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser

Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret
```

こんな感じの yaml ファイルで設定を定義します。

```yaml
GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10
```

この辺はおまじないです。

```yaml
Globals:
  Alias:
    ApplicationUserName: InGame
```

作成するユーザ名の定数を宣言しています。

```yaml
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}
```

名前が ApplicationUserName(InGame) のユーザを作成するという設定です。

```yaml
  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser
```

ApplicationAccess のセキュリティポリシーを割り当てる設定です。
DependsOn でユーザの作成より後に実行するようにしています。

```yaml

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser
```

InGameユーザのクレデンシャルを発行する設定です。
こちらも、DependsOn でユーザの作成より後に実行するようにしています。

```
Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret
```

クライアントIDとクライアントシークレットの値を保存します。
ここで指定しているパスは、[クレデンシャルの新規作成API](https://app.gs2.io/docs/sdk/identifier.html#gs2-sdk-identifier-create-identifier-createidentifier) の戻り値の値です。

#### GS2-Deploy にアップロードしてみる

サイドメニューから 管理＞Deploy を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/2f3eff9e-413b-b8d3-7756-d20f04b621cc.png)

続けて『スタックの新規作成』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/48abf9e5-1206-c43b-22d7-b343c665ef2c.png)

スタック名に適当に名前を付けて、テンプレートデータに先ほどの yaml ファイルを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/d35bd886-4c12-cf1b-33f0-b589664a6381.png)

しばらく待つと作成が完了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/ec5329cb-4d4b-bf75-35dd-a3437f48dcaa.png)

アウトプットタブを選択すると、クレデンシャルの内容が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/d96924a0-2579-0ed1-7553-3b619e1971e8.png)

## GS2-Account でアカウントを作ってみる

アカウントを作成するためには、アカウントのネームスペースと、アカウントの認証に使用する暗号カギを作成する必要があります。

### GS2-Deploy でアカウントの初期設定をする

以下のテンプレートを GS2-Deploy でデプロイします。

```yaml
GS2TemplateFormatVersion: "2019-05-01"
Description: GS2-Account initialize template Version 2010-06-26

Globals:
  Alias:
    AccountNamespaceName: game-0001
    KeyNamespaceAccountAuthentication: account-encryption-key-namespace
    KeyAccountAuthentication: account-encryption-key

Resources:
  KeyNamespaceAccountAuthentication:
    Type: GS2::Key::Namespace
    Properties:
      Name: ${KeyNamespaceAccountAuthentication}

  KeyAccountAuthentication:
    Type: GS2::Key::Key
    Properties:
      NamespaceName: ${KeyNamespaceAccountAuthentication}
      Name: ${KeyAccountAuthentication}
    DependsOn:
      - KeyNamespaceAccountAuthentication

  AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: ${AccountNamespaceName}

Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
  KeyAccountAuthenticationKeyId: !GetAttr KeyAccountAuthentication.Item.KeyId
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/d2bc1530-3519-835c-f7ea-c88ecbc886c8.png)

できました。

### SDK のダウンロード

まずは Unity 向けのSDKをダウンロードします。

https://app.gs2.io/docs/game-engine.html#gs2-sdk-for-unity

#### unitypackage を実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/dc345dde-8859-a78d-33b8-4b7423b4a347.png)

unitypackage を実行してアセットをインポートします。

#### インストーラーを実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/7c6948b0-1d77-c131-8cc6-433a08a5d718.png)

メニューに Game Server Services が増えるので 『インストーラー』 を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/76f02cf5-3ce4-5eae-3bb4-34f9e62f4f28.png)

インストールを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/5b25ad32-9c80-3c53-1a83-b920c5d8a035.png)

なんか出てくるのでしばらく待ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100723/3b633e04-d345-3831-ad56-ce6d0c3b0a1a.png)

ログインボタンが出てきますが、そっと閉じます。

### アカウントを作成するコードを記述

```cs
using System;
using System.Collections;
using System.Collections.Generic;
using Gs2.Core;
using Gs2.Unity.Gs2Account.Model;
using Gs2.Unity.Gs2Account.Result;
using Gs2.Unity.Util;
using UnityEngine;

public class Gs2AccountSample2 : MonoBehaviour
{
    // GS2-Identifier で発行したクライアントID
    public string clientId;

    // GS2-Identifier で発行したクライアントシークレット
    public string clientSecret;

    // アカウントを作成する GS2-Account のネームスペース名
    public string accountNamespaceName;

    // アカウントの認証結果に付与する署名を計算するのに使用する暗号鍵
    public string accountEncryptionKeyId;

    void Start()
    {
        StartCoroutine(Create());
    }

    public IEnumerator Create()
    {
        // GS2 SDK のクライアントを初期化

        Debug.Log("GS2 SDK のクライアントを初期化");

        var profile = new Gs2.Unity.Util.Profile(
            clientId: clientId,
            clientSecret: clientSecret,
            reopener: new Gs2BasicReopener()
        );

        {
            AsyncResult<object> asyncResult = null;

            var current = profile.Initialize(
                r => { asyncResult = r; }
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // クライアントの初期化に失敗した場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Client(profile);

        // アカウントを新規作成

        Debug.Log("アカウントを新規作成");

        EzAccount account = null;

        {
            AsyncResult<EzCreateResult> asyncResult = null;

            var current = gs2.Account.Create(
                r => { asyncResult = r; },
                accountNamespaceName
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // アカウントが作成できなかった場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // 作成したアカウント情報を取得
            account = asyncResult.Result.Item;
        }

        // GS2 SDK の終了処理

        Debug.Log("GS2 SDK の終了処理");

        {
            // ゲームを終了するときなどに呼び出してください。
            // 頻繁に呼び出すことは想定していません。
            var current = profile.Finalize();

            yield return current;
        }
    }

    private void OnError(Exception e)
    {
        Debug.Log(e.ToString());
    }
}
```

### クライアントの初期化

```cs
        // GS2 SDK のクライアントを初期化

        Debug.Log("GS2 SDK のクライアントを初期化");

        var profile = new Gs2.Unity.Util.Profile(
            clientId: clientId,
            clientSecret: clientSecret,
            reopener: new Gs2BasicReopener()
        );

        {
            AsyncResult<object> asyncResult = null;

            var current = profile.Initialize(
                r => { asyncResult = r; }
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // クライアントの初期化に失敗した場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Client(profile);
```

クライアントIDとクライアントシークレットを使用して初期化を行います。

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

```cs
        // アカウントを新規作成

        Debug.Log("アカウントを新規作成");

        EzAccount account = null;

        {
            AsyncResult<EzCreateResult> asyncResult = null;

            var current = gs2.Account.Create(
                r => { asyncResult = r; },
                accountNamespaceName
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // アカウントが作成できなかった場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // 作成したアカウント情報を取得
            account = asyncResult.Result.Item;
        }
```

gs2.Account.Create を呼び出すとアカウントを作成できます。

# 次回予告

導入手順だけで結構な量になってしまいました。
次回はアイテムの所持状況の管理APIを作ってみようと思います。

[Game Server Services で所持品を管理](https://qiita.com/kazutomo/items/411e4a6c00b51865fe43)