GS2とUnityでオンラインゲームを開発する その1GS2を利用する前準備編

通信を実装したい

今回の記事を書くに至った経緯を説明します。まず、僕はゲーム開発をするにあたって通信を実装したかったためいろいろ調べていました。UnityではPUN2っていうのを使う人が多いのかな?PUNって何?から始まりいろいろ調べていたら、最近GS2ってものに出会ったので、そのまま調べていたら、あれ、なんだこれ良さそう。ということで使いたくなってしまいました。まだ文献なども少なそうだし、自分が使っていく中で気づいたことなどブログに残せたらいいかなと思い、今に至ります。複数回に分けて書いて行こうと思っているので、ちょくちょく更新していければいいかなと思っています。

Unityにおける通信周りの選択肢

Unityで通信を実装したい時いろいろな方法が考えられます。現時点(2021年2月)でUnityで通信をしたいと思った時の実装の手段としては

  • Photon PUN
  • Photon Quantum
  • Mirror
  • MLAPI

などのサービスを使うのが主流だと思われます。特にPUNは参考文献も多く、初心者や個人開発者に向いていると思います。しかしPhoton Cloudを使うと無料の最大接続数は20人まで、最大メッセージ数は500/(秒・ルーム)となっており制限が厳しくなっています。詳しい比較に関してはUnity公式のブログに詳しく書かれていたため、こちらをご覧ください。https://blogs.unity3d.com/jp/2020/09/08/choosing-the-right-netcode-for-your-game/

また最近ですとEpic Online Servicesという、リアルタイム通信対戦ゲーム開発のためのサービスも発表され、Unityでも使えるということで話題になっているようです。そっちも興味がありますね。それに加えて、上記のサービス意外にもMicrosoft AzureのPlayfabやAWSのGameLiftなど様々な選択肢があるみたいです。たくさんあって難しい。よくわからない人はPUN2を使うのが無難と言えそうです。

GS2とは?

んでじゃあGS2ってなんですかって話なんですけど、ホームページをまず見てみましょう。

https://gs2.io/

ホームページによると、クライアント開発だけでゲーム開発ができるようにサーバー、SDKの提供をしてくれているみたいですね。

UnityやUnreal Engineなどのゲームエンジンなどでは、クライアント開発を協力にサポートしてくれますが、サーバー側の処理はそれぞれの企業が独自でシステムを作り上げる必要があり、GS2はそこを解決してサーバー側の開発をできるだけ少なくすることができるようにしてくれるというイメージなのかなと思っています。

提供中のサービスは以下のようなものがあるらしいです。

  • アカウント
  • ゲーム内通貨
  • ショップ
  • レベル
  • スタミナ
  • マッチメイキング
  • ランキング
  • イベントスケジュール
  • 課金通貨
  • 消費型アイテム
  • ガチャ
  • プレゼントボックス
  • チャット
  • リアルタイム通信
  • ゲーム内プッシュ通知
  • 回数制限

凄そう。上記のようなゲーム特有の様々なシステムを簡単に導入できるのは良さそうですね。導入する際も一部の機能だけ導入するといったことも簡単にできるらしく既存のサービスをカスタマイズする形で利用することもできそうです。

またAWSやGCPを使ったハイブリッドクラウドを提供していて、サーバーダウンの心配をほとんどしなくていいのも魅力の一つらしいです。個人の規模ではあまりわかりませんが、企業などが利用する際にはとても重要なことだと思います。

さらに注目すべきは次の点です。

それはIndivisual プランの存在です。Indivisualプランは過去十二ヶ月の売り上げが1000万円以下の場合、このGS2の機能を全て無料で使えるという太っ腹なプラン。個人ゲーム開発者にとってはこんな嬉しいことはないでしょう。というわけで今のところいいとこずくしのGS2ですが、これから実際に使ってみてその使い心地を調べていきたいと思っています。

GS2の管理画面にアクセスする

GS2のアカウントを作成する

まずはホームページから無料登録します。アカウントの登録はゲームの開発管理者が行えばいいようです。必須項目はメール、名前、パスワードのみで簡単でした。

アカウント登録画面

登録ボタンを押したら認証メールが届くのでメール内のリンクをクリックして登録を完了します。

プロジェクトを新規作成する

次に先ほど登録した情報を使って管理コンソールへサインインすると以下のような画面に飛びます。GS2ではブラウザ上の管理コンソールでプロジェクトを管理します。プロジェクトはゲームと直接関連付けられるのでゲーム一つにつき一つのプロジェクトを作成すればいいみたいです。あるプロジェクトから他のプロジェクトには干渉することができません。

プロジェクト作成前

プロジェクトの新規作成ボタンから実際にプロジェクトを作成します。必須項目はプロジェクト名だけみたいですね。プロジェクト名以外の設定はプロジェクト設定ボタンから後からでも変更可能です。プロジェクト新規作成後は以下のような画面になります。UrbanMythsというプロジェクトが追加されていますね。(UrbanMythsとは現在作成中ゲームの仮タイトルです)

プロジェクト一覧ページ

GS2のサービスについて

プロジェクトを作成できたところで、GS2のサービスの概略、使い方などを一度整理したいと思います。GS2はGS2-AccountやGS2-Moneyなど、機能ごとにサービスを提供しており、一般的なProfessionalプランでは、各API呼び出しごとに0.02円の利用料金がかかるようになっています。ちなみにEnterpriseプランというものもあり、こちらはMAUあたり30円~100円の固定額で、全ての機能が利用できるようになるみたいです。実際の利用料金はProfessionalプランと比較して、安い方の請求が行われるようです。まあIndivisualプランの方は、気にする必要ないんですけどね。ですが、API呼び出しごとに料金が加算されるという仕組みは、このサービスの仕組み、構造と関連していると思うので知っておいた方が何かとしっくりくるのではないでしょうか。

GS2-Identifierとは

さて、GS2の各サービスでは様々なAPIが利用できるようになっているわけですが、各API利用時には認証情報が必要となります。この認証情報のことをクレデンシャルと呼び、GS2においてはユーザー単位で管理されているため、ユーザーごとに異なる権限を与えられるようになっています。あるユーザーの権限の詳細を定義したものをセキュリティポリシーと呼び、ユーザーにセキュリティポリシーを割り当てることで権限を設定します。セキュリティポリシーはJSON形式で、各APIに対する呼出可否を記述するようになっています。GS2にはデフォルトで二種類のセキュリティポリシーが用意されており、それらを使うこともできますし、JSONファイルを用意することで簡単にカスタマイズすることも可能です。ちなみに、デフォルトの二種類のセキュリティポリシーとしては、あらゆるAPIを呼出可能なAdministratorAccessと、チート行為に繋がるような操作ができるAPIを呼び出すことができないような設定のApplicationAccessが用意されています。公式ドキュメントのポリシードキュメントの例

{
    'Version': '2016-04-01',
    'Statements': [
        {
            'Effect': 'Allow',
            'Actions': [
                'Gs2Account:Create*',
            ],
            'Resources': ['*'],
        },
    ]
}

Versionにはバージョンの記入。Statementsに実際に権限設定を記述しています。Actions に呼び出せるアクションを羅列し、Resources に操作出来る対象リソースを羅列するようです。ActionsのGs2Account:CreateはGS2-AccountサービスのCreateアクションという意味で、このセキュリティポリシーを割り当てられたユーザーはその操作のみ可能ということです。Resourcesには末尾にのみワイルドカードが使用可能なようです。

これらの権限管理を行うのはGS2-Identifierと呼ばれるサービスです。データ構造としては以下のようになっています。

  • ユーザー(User)
    • クレデンシャル(Identifier)
    • パスワード(Password)
    • 割り当てられたセキュリティポリシー(AttachSecurityPolicy)
  • セキュリティポリシー(SecurityPolicy)

APIを呼び出す際はクレデンシャルの保有者であるユーザーに割り当てられているセキュリティポリシーをもとに権限を判断して処理します。複数のセキュリティポリシーを割り当てることも可能で、その場合はいずれかのセキュリティポリシーで許可されていればAPIは利用可能みたいです。実際のステップとしては

  1. セキュリティポリシーを用意
  2. ユーザーの作成。セキュリティポリシーの割り当て
  3. 2で作成したユーザーでAPI呼び出し、または管理コンソールにログイン

といった流れになるみたいです。GS2のアカウント作成は一人の管理者が行いましたが、GS2-Identifierでユーザーを複数作成することで、複数人で管理することができるということですね。

GS2-Deployとは

GS2-Identifierに加えてもう一つ、最初に知っておくべきサービスがあります。それはGS2-Deployです。GS2-Deployはサービスのデプロイを自動化してくれるサービスで、使用するリソースや設定をテンプレートファイルに記述し、テンプレートを読むこむだけで自動で設定を反映してくれるといったものです。Dockerとその設定ファイルのようなイメージなのかなと思っています。以前Dockerの記事をかいたのでイメージしやすかったですね。

GS2では各リソースの作成などを管理コンソールから一つ一つ生成、管理できるのですが、これらの操作をyaml形式のテンプレートとして記述することができるようにしたものがGS2-Deployみたいです。先ほどのGS2-Identifierでもクレデンシャルの設定は管理コンソールから行えますが、GS2-Deployを利用し、テンプレートファイルを使うのが便利です。(次章参照)

GS2-Deployを使うことで

  • テンプレートファイルが同じであれば同じ環境を構築することができるため、例えば本番環境と開発環境で違うプロジェクトを使用していた場合、環境は同じものを簡単に用意することができる。
  • テンプレートファイル自体をバージョン管理することで、環境のバージョン管理ができる
  • 連番アイテム生成などの単純作業の効率化が図れる

などのメリットがあるため、積極的に使用するのが良さそうです。

GS2-Deployのデータ構造は以下のようになっています

  • スタック
    • リソース
    • アウトプット

スタックはテンプレートを指定して作成します。作成時にテンプレートをもとにして、リソース、アウトプットが反映されます。変更したテンプレートを再適応することでリソースは自動的に作成、更新、削除されます。

いろいろとGS2独自の概念が出てきてややこしくなってきましたが、一度おさらいしておくと、今のところ二つのサービス、GS2-IdentifierとGS2-Deployを紹介しました。GS2-Identifierはユーザーとユーザーの権限管理を行うサービスで、GS2-DeployはGS2の環境設定をテンプレートファイルに記述することで自動で環境設定してくれるサービスです。それでは、実際に二つのサービスを使ってみましょう。

GS2-DeployとGS2-Identifierを使ってクレデンシャルを設定する

クレデンシャルの設定はGS2-Identifierの管理画面から、もしくはGS2-Deployを利用することで設定できる、ということが前章で分かって頂けたかと思います。

ということでGS2-Deployを利用してクレデンシャルの設定をしていきます。

まずは、スタックを作成します。スタックの作成にはテンプレートが必要なため公式サイトのドキュメントからクレデンシャルを発行するテンプレートをダウンロードしましょう。

https://app.gs2.io/docs/index.html#get-start-issue-credentials-deploy-gs2-deploy

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

Globals:
  Alias:
    ApplicationUserName: application

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

ダウンロードしたテンプレートはこんな感じになっていました。先ほどのGS2-Identifierのデータ構造をもとにどんな意味か見ていきましょう。

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

まずはじめの二文はテンプレートのバージョンとテンプレートの説明文を記入してます。

Globals:
  Alias:
    ApplicationUserName: application

続いてこちらの項目ではエイリアスの設定をしています。今回の場合applicationという文字列をApplicationUserNameというエイリアスとして登録していますね。つまりユーザー名をここで指定していて、これ以降ユーザー名はApplicationUserNameというエイリアスを用いて指定しています。なので後からユーザー名を変えたい場合は、applicationの部分だけ書き換えれば全て書き換わることになるわけです。

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

ここから実際に生成するリソースを一つずつ設定していきます。一つ目はIdentifierApplicationUserとありますが、ここは任意の名前をつけるみたいです。TypeとしてGS2:Identifier:Userを指定してあるのでGS2-Identifierサービスのユーザーリソースを生成していることがわかります。Propertiesにはユーザ名を先ほどのエイリアスを用いて指定しています。ここでGS2-SDKのドキュメントを見るとUserのパラメータは下記のようになっていました。

パラメータデータ型必須説明
userIdstringtrueユーザID
ownerIdstringtrueオーナーID
namestringtrueユーザー名
descriptionstrongfalseユーザーの説明
createdAtlongtrue作成日時
updatedAtlongtrue最終更新日時
Userのモデル

つまり必須項目はユーザID、オーナID、ユーザ名、作成日時、最終更新日時ということですがこのうちユーザIDとオーナID、作成日時、最終更新日時は自動で割り当てられると考えるのが自然なので、ユーザ名のみを指定すれば正しく生成されるということでしょう。ちなみにオーナーIDとは{アカウントID}${プロジェクトID}で生成される文字列のようです。また、ややこしいですが、アカウントIDとユーザIDは別物でアカウントIDはGS2のアカウントを認識するID、ユーザIDはゲームプレイヤを識別するID、つまりAPIを利用するユーザのIDということになります。

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

次がIdentifierApplicationUserAttachPolicyという名前で登録されたリソースですがこちらのTypeはGS2:Identifier:AttachSecurityPolicyとなっています。つまり先ほどのGS2-Identifierのユーザに割り当てられるセキュリティポリシーを設定する項目ということです。AttachSecurityPolicyについてもGS2-SDKのドキュメントからパラメータを調べてみると、下記のようなパラメータを持つことがわかります。

パラメータデータ型必須説明
userIdstringtrueユーザのGRN
securityPolicyIdslist[string]trueセキュリティポリシーのGRNのリスト
attachedAtlongtrue作成日時
AttachSecurityPolicyのモデル

先ほどと同じように作成日時は自動生成されると考えるとuserIdとsecurityPolicyIdsを指定すればいいように思いますが実際に指定しているのはuserNameとsecurityPolicyIdsですね。userNameを指定しても作ってくれるんですね。

securityPolicyIdsの指定もよくわかりませんがgrn:gs2::system:identifier:securityPolicy:ApplicationAccessとあるのでやっていることとしては先ほど紹介したデフォルトのセキュリティポリシーであるApplicationAccessを割り当てているということですね。チートができないように権限設定がされたセキュリティポリシーです。

最後のDependsOnの項目には先ほど指定したリソースのIdentifierApplicationUserが指定されています。これはIdentifierApplicationUserの生成が終わってからIdentifierApplicationUserAttachPolicyの生成を行うという順序付けを行っているものだと思います。

そして三つ目のリソースの設定がこちら

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

TypeがIdentifierなのでクレデンシャルの生成だとわかります。これまで同様にクレデンシャル(Identifier)のパラメータを調べると次のようになっています。

パラメータデータ型必須説明
ownerIdstringtrueオーナーID
clientIdstringtrueクライアントID
userNamestringtrueユーザー名
clientSecretstringtrueクライアントシークレット
createdAtlongtrue作成日時
Identifierのモデル

ownerId, clientId, clientSecret, createdAtは自動で生成されるでしょうね。と考えれば指定するのはuserNameだけ。なるほど、だんだん分かってきました。(ドキュメントなど知らずに推測で考えているので、解釈違いでしたらすみません。ドキュメントの場所を教えてください。)クライアントシークレットは後ほどクレデンシャルを利用する時に使うみたいです。

そして最後!

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

Outputsは何か変数を吐き出すというイメージですかね。あとでわかるんですけど、ここに記述しているApplicationClientIdとApplicationClientSecretは管理コンソールの今回作成したスタックのアウトプット蘭から見れるようになります。なんでここでわざわざ吐き出す必要があるんでしょう?とりあえず一回このDeployを実行してみましょう。

管理コンソールからプロジェクトメニューの右側にある管理メニューへボタンを押しダッシュボードへ移動します。メニューの管理 > Deployを選択します。

ダッシュボードからGS2-Deploy管理画面へ移動
Deploy管理画面

スタックの新規作成をします。テンプレートには先ほどダウンロードしたものを使用します。テンプレート名はとりあえずよくわからなかったのでinitialize_credencialにしました。

スタック生成後の詳細画面

スタックの実行状態欄がはじめは作成中になっていますが数分後にリロードすると作成完了になりました。スタックの選択画面の状態がCREATE_COMPLETEになっていることからも確かめられます。

スタックの状態がCREATE_COMPLETEとなっている

スタックの詳細画面のアウトプットタブでApplicationClientIdとApplicationClientSecretの値が表示されています。

スタックのアウトプットタブ表示画面

ここでDeployの役割を一度考えてみるとDeployはGS2-Identifierの設定を自動で行うという役割を持っていました。つまり、今Identifierの管理画面に行けば、設定がみられるはず。管理コンソール>Identifierに飛ぶとユーザー一覧にapplicationという名前のユーザが表示されていることを確認できました。

Identifier管理画面

詳細ボタンを押して、クレデンシャルというタブがあるのを確認しました。お、じゃあここからclientIdもclientSecretの値も確認できそう、と思ってクリックしてみると

クレデンシャルタブの表示

clientIdを確かめることはできましたが、Identifierのプロパティの一つであるclientSecretは見当たりませんね。ここでクレデンシャルを手動で新規作成してみました。

クレデンシャルを手動で生成

あ、そういうことね。クライアントシークレットは生成時にしか確認できないものらしいです。ここでGS2-Deployでやっていたことがようやく理解できました。Outputにクライアントシークレットを指定することでDevelopのスタックのアウトプット画面からそれを確認できるようにしていたわけです。ついでにあとで使うであろうclientIdも同時に吐き出したのでしょうか。真に理解をしたのかはわかりませんがとりあえず腑に落ちたのでよしとしましょう。ちなみに今回作成したクレデンシャルはすぐに削除しておきました。

まとめ

さて、GS2という新しいサービスに出会って一日が過ぎましたが調べれば調べるほど良さそうに思えてくるサービスです。まだ実際に使うところまでいっていないのであれですけど、公式ドキュメントは日本語で読みやすいし、とても期待が高まっています。今回やったことを一度おさらいしておきましょう。

  • GS2とはゲームサーバエンジンであり、アカウントやクエストなど、ゲーム特有の機能の実装などを簡単に行うことができ、クライアント開発だけでゲームを作れるようになる画期的なサービスである。
  • GS2の料金プランは三種類あるが、過去12か月の売上が1000万円に満たなければ全ての機能を無料で使うことができるIndivisualプランが存在する。
  • GS2は機能ごとにサービスを用意しており、必要なものだけをカスタマイズできるようになっている。今回はその中でもほぼ全ての利用者が使うことになるであろうGS2-IdentifierGS2-Deployについて触れた
  • GS2-IdentifierはGS2のAPI利用時の権限を管理するサービスである。ユーザごとにセキュリティポリシーと呼ばれる権限ルールを割り当てることで管理する。実際の認証はクレデンシャルと呼ばれる認証情報を使って行われる。
  • GS2-DeployはGS2の各種設定、環境設定をテンプレートファイルの記述から読み取り自動で設定してくれるサービスである。生成するリソースと後から管理コンソールで表示したいアウトプットをyamlファイルに記述することで簡単に設定できる。
  • GS2-Deployを使ってGS2-Identifierのクレデンシャルを生成するところまで今回は行った。

まだGS2と出会ってから一日二日しか経っていないので、解釈違いなどあると思います。多めにみてください。気付いたら追記、修正もしていくつもりです。また、今回は管理コンソールしかいじっていないので次回以降、実際にUnityをつかってサービスを利用していきたいと思っています。長くなりましたが、ここまで読んでくださりありがとうございました。

この記事を書いた人:hal-bo

hal-bo