GS2 Blog

Game Server Services(https://gs2.io/) の最新情報をお届けします

マイクロサービス間の連携の設定が簡素化されました

はじめに

GS2 は多数のマイクロサービスを提供しており、多くのケースはトランザクション処理として、《消費アクション》と《入手アクション》として抽象化されています。

一方で、トランザクションを実行するために必要な GS2-Distributor や GS2-JobQueue
各種暗号処理で利用する GS2-Key の暗号鍵、各種通知処理で使用する GS2-Gateway といったマイクロサービスとの関連付けは各マイクロサービスのネームスペース設定として設定が必要です。

この設定漏れや誤りによる不具合報告を多数頂戴する状況から、利用者にとってもGS2にとってもボトルネックになっていると感じていました。

変更の内容

2023年8月にはプロジェクトの作成時にこれらの設定のややこしいマイクロサービスに「default」という名前でネームスペースを作成するようになりました。
これによって、マネージメントコンソールを初めて操作する際でも、とりあえず選択可能な項目を選択することで設定を完了できるようになりました。
しかし、実際には GS2-SDK を利用する際にもこれらの値を正しく設定しなければ、意図する動作にならないケースがあり、まだこの対応では不十分でした。

今回の更新で、サーバー・SDKを共に大規模な更新を行い、これらの連携用の設定が未設定の場合は「default」ネームスペースを使用して動作するようになります。

変更の適用方法

サーバーサイドは自動的に未設定の場合でもデフォルトネームスペースが利用されます。
もし、プロジェクトの作成が 2023年8月 より前で、デフォルトネームスペースが作成されていない場合は以下の GS2-Deploy テンプレートを適用することで、デフォルトネームスペースを後から作成することができます。

GS2TemplateFormatVersion: "2019-05-01"

Globals:
  Alias:
    ApplicationUserName: default
    KeyNamespaceName: default
    KeyName: default
    DistributorNamespaceName: default
    GatewayNamespaceName: default
    JobQueueNamespaceName: default

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

  KeyNamespace:
    Type: GS2::Key::Namespace
    Properties:
      Name: ${KeyNamespaceName}

  Key:
    Type: GS2::Key::Key
    Properties:
      NamespaceName: ${KeyNamespaceName}
      Name: ${KeyName}
    DependsOn:
      - KeyNamespace

  GatewayNamespace:
    Type: GS2::Gateway::Namespace
    Properties:
      Name: ${GatewayNamespaceName}

  DistributorNamespace:
    Type: GS2::Distributor::Namespace
    Properties:
      Name: ${DistributorNamespaceName}
      AutoRunStampSheetNotification:
        GatewayNamespaceId: !GetAttr GatewayNamespace.Item.NamespaceId

  JobQueueNamespace:
    Type: GS2::JobQueue::Namespace
    Properties:
      Name: ${JobQueueNamespaceName}
      EnableAutoRun: true

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

あとは、GS2-SDK を更新してください。Unity の場合は「v2023.11.7」以降を利用するようにしてください。

トランザクション処理の投機的実行機能が Unreal Engine 5 をサポートしました

gs2.hatenablog.com

先日、通信待ちをすることなく通信後の結果を想定して GS2-SDK がもつローカルキャッシュを投機的に更新することで
SDKから取得できる値を先行して更新後の値を取得できるようにする仕組みのリリースを発表しました。

前回リリースの段階では、Unity 向けの SDK でのみ本機能が実装されていましたが
この度 Unreal Engine 向けの SDK でも同様の対応が行われました。

細かな仕様は Unity と同様ですので、昨日の詳細については前述のブログ記事を参照ください。

トランザクション処理の投機的実行機能が追加されました

はじめに

GS2におけるトランザクション処理というのはユーザーデータの増減処理を指します。
たとえば、「課金通貨を消費してスタミナを回復する」というような操作です。

機能追加の背景

GS2はレスポンスタイムの最適化を日々行なっており、数百msのオーダーで処理が実行されます。
しかし、通信が完了するまでUIを更新しないとこの数百msのラグが違和感を生んでしまいます。

そこで、ユーザー体験を最適化するために投機的実行機能を実装しました。

追加された機能の詳細

GS2-Showcase の Buy や GS2-Exchange の Exchange 関数に第二引数

bool speculativeExecute = true

が追加されました。ここで投機実行機能を有効化するかを指定することができます。
記載の通り、デフォルトで有効化されます。

投機的実行のメカニズム

投機的実行処理を有効にしてトランザクション処理を実行すると、GS2-SDK は通信を開始する前にトランザクション実行後に期待される値でSDKがもつローカルキャッシュを更新します。
これによって、GS2-SDK を経由して取得される値も先行して期待される値に更新されます。

ローカルキャッシュを書き換えますが、このキャッシュの有効期限は10秒に設定され
10秒経ってもトランザクション処理が正常に完了しない場合は改めて最新の値をサーバーから取得します。
10秒以内にトランザクションが完了すれば、サーバーからのトランザクション完了通知を受け取ってキャッシュの有効期限がデフォルト値であれば15分に延長されます。

投機的実行できない処理

GS2-Money のストアプラットフォームのレシート検証や、GS2-Lottery の抽選処理などサーバーが処理しなければ結果がわからない処理については投機的実行は行われません。
投機的実行ができないトランザクション処理が含まれていた場合、以下の警告がコンソールに出力されます。

Speculative execution not supported on this action: XXX:XXX

投機的実行ができないだけで処理自体は今まで通り行われますので、サーバーからの完了通知をもってローカルキャッシュの更新が行われます。
そのため、この警告については深く気にする必要はありません。

投機的実行の入れ子

投機的実行処理はトランザクション処理が入れ子構造になっていても適用されます。
たとえば、GS2-Showcase で GS2-Exchange の交換処理を実行する入手アクションが設定された商品が登録されており、その商品を購入した場合は、GS2-Exchange の交換処理についても投機的実行が行われます。

連続的な処理でのチャタリング

投機的実行処理によって通信処理が完了しなくてもUI上は想定される最新の値を表示するようになったことで
交換処理のAPIを連打した時にUIのチャタリングが生じるようになる可能性があります。

具体的には以下のような順番で処理が発生した場合を想定してください。

アイテムを1個入手(処理A) -> アイテム数量1
アイテムを1個入手(処理B) -> アイテム数量2
サーバーで処理Aが完了 -> アイテム数量1
サーバーで処理Bが完了 -> アイテム数量2

この場合、一瞬アイテムの数量が 2 から 1 に巻き戻って表示されます。

このように高頻度(1秒に何度も)APIを呼び出すのであれば、API呼び出しをバッファリングし GS2-Showcase であれば Quantity、GS2-Exchange であれば Count の値を指定するようにすることで通信回数を削減で、チャタリングの発生を回避できます。

新機能への対応に関する注意事項

GS2 では定期的に新機能が追加されており、トランザクション処理も追加されています。
未知のトランザクション処理が含まれている場合は、投機的実行ができないトランザクションアクションと同様の警告が表示されるだけで動作自体には大きな問題は生じません。
しかし、積極的にSDKを最新に更新することで、最新の投機的実行処理にも対応でき、最適なUXを実現できます。
不具合の修正も頻繁に行われていますので、出来る限り最新のSDKを利用するようにしてください。

GS2-StateMachine で利用する GSL にスクリプトを直値で指定できるようになりました

はじめに

GS2-StateMachine はステートマシンをサーバーサイドで管理し、クライアントから届くメッセージを元に状態遷移することで
チート行為に対する耐性をたかめつつ、自由度の高いスクリプティングを実現する機能を提供しています。

機能追加の背景

GS2-StateMachine が管理するステートマシンは GS2 State Language(GSL) を使用して定義します。
新しいステートに遷移した際にスクリプトを実行して、ステートマシンが持つ状態変数を書き換えることができます。
従来はこのスクリプトの指定には GS2-Script が管理するスクリプトのIDを指定することで定義していました。

しかし、GSLとスクリプトの実体が分離してしまい、見通しが悪くなってしまう状況が発生していました。

機能追加の詳細

StateMachine MainStateMachine {
  Variables {
  }

  EntryPoint Task1;

  Task Task1(int initCounter) {
    Event StartLoop();
    Event Error(string Reason);

    Payload {
      result = {
          event="Pass",
          params={},
          updatedVariables=args.variables
      }
    }
  }

  PassTask Pass;

  ErrorTask Error(string reason);

  Transition Task1 handling Pass -> Pass;
}

こちらの例のように Task 内の Payload セクションで直接 Lua スクリプトを記述できるようになりました。
例では Task1 に遷移した際に以下のスクリプトを実行します。

      result = {
          event="Pass",
          params={},
          updatedVariables=args.variables
      }

スクリプトを実行した結果、Pass というメッセージを自身のステートマシンへ発します。

    Transition Task1 handling Pass -> Pass;

Task1 ステートにいる時に Pass というメッセージを受け取ると、Pass ステートに遷移します。
Pass ステートは PassTask なので、ステートマシンの終端を表すステートに遷移しステートマシンは起動直後に終了します。

エクスポートしたユーザーデータをインポートできるようになりました

機能追加の背景

gs2.hatenablog.com

先日各国の法令遵守のために、ユーザーデータをエクスポートして提供できるようにしたり、ユーザーデータを完全に削除する機能の提供開始をアナウンスしました。
今回の更新はこのエクスポートしたユーザーデータを異なるアカウントやプロジェクトにインポートする機能の提供開始をお知らせします。

追加された機能の詳細

この機能の追加によって、お客様が何らかの問題を報告してきた際に製品環境でユーザーデータをエクスポートして
QA環境や開発環境にユーザーデータをインポートして、実際にお客様のプレイデータを再現した状態で動作確認をすることが可能となります。

先日、エクスポートメニューがプロジェクトメニューに追加されたと告知しましたが、その隣にインポートメニューが追加されました。

インポートを実行したいプロジェクトがアクティブな状態でインポートメニューを選択すると、インポート履歴ページが開きますので「ユーザーデータのインポートを開始」を選択します。

ユーザーデータをインポートする際には元のユーザーデータとは異なるユーザーIDとしてインポートが可能です。
あとは、他のプロジェクトでエクスポートした zip ファイルを選択してインポートを実行するだけです。

国外の個人情報保護のための法令に対応するための機能が追加されました

機能追加の背景

この10年の間に 欧州では GDPR、米国では CCPA などの個人情報を取り扱う上で課題となる法令が次々と制定されています。
その中には対応するのに相当な工数を必要とする内容もあり、サービス提供者を悩ませています。

追加された機能の詳細

  • GS2 が提供する全てのマイクロサービスから、特定のユーザーIDに関連づけられたデータの全データをzip形式で取得
  • GS2 が提供する全てのマイクロサービスから、特定のユーザーIDに関連づけられたデータの完全な削除

上記2つの機能が追加されました。

完全な削除については、完全な削除を必要とする法律と一定期間保存しなければならない法律が国ごとにあり整合性が取れていないのが現状です。
そのため、顧問弁護士やリーガル部門の指導のもと機能を利用することを強く推奨します。

また、ここで提供する機能は全て GS2 内部で管理しているデータについてとなり、GS2 の外に持ち出されたデータについては関与しません。

追加された機能の利用方法

マネージメントコンソールのサイドメニューのプロジェクトメニュー内に「ユーザーデータをエクスポート」「ユーザーデータを完全に削除」の2つの項目が追加されています。

ユーザーデータをエクスポート

「ユーザーデータをエクスポート」 を選択するとエクスポート履歴が表示されます。
「ユーザーデータのエクスポートを開始」を選択します。

エクスポートを実行したいユーザーのユーザーIDを入力して「開始」ボタンを押します。

全てのマイクロサービスから出力が完了すれば、エクスポートデータが24時間の間 DL可能となります。

ユーザーデータを完全に削除

「ユーザーデータを完全に削除」 を選択すると削除履歴が表示されます。
「ユーザーデータの削除を開始」を選択します。

削除を実行したいユーザーのユーザーIDを入力して「開始」ボタンを押します。

UIがエクスポートと類似しているため、削除の場合は一段確認の行程が追加されています。
本当に実行したい場合は「開始」ボタンを押します。

全てのマイクロサービスで削除が完了していれば、該当のユーザーに関するデータはGS2上から完全に削除されています。

強化処理の UI Kit サンプルが追加されました

github.com

サンプルを実行すると、自動的に3つの武器の入手処理が行われ一覧表示が行われます。

武器を選択すると、強化素材の選択メニューが表示されます。

スライダーを動かすと、予測経験値獲得量が連動します。

Execute をクリックすると、強化が実行されます。

Unleash タブを選択すると、レベルキャップの引き上げができますが
まだレベルキャップに到達していないので、実行できません。

レベルキャップまで強化をします

すると、Unleash タブで進化素材を消費する画面になります。

Execute を選択すると、レベルキャップが5上がります。

再度レベルキャップまで強化します。

レベル10 -> 15 と レベル 15->20 では異なる進化素材が必要となります。

このサンプルではレベル30まで進化できるようになっています。

(C) Game Server Services, Inc.