GS2-Dictionary

図鑑機能

GS2-Dictionary では、ゲーム内で入手したアイテムやキャラクターの図鑑機能を実現します。

基本的に、GS2-Inventory のシンプルな実装バージョンと捉えていただければよく、入手済み・未入手の2値の所持状態を管理できます。

図鑑以外の用途にも使用できます。たとえばアバターパーツの所持状態はいい例です。 アバターパーツを持っているかは、パーツごとに2値で状態管理できれば十分なので GS2-Dictionary 向きです。

ただし、不要なパーツを売却できる仕様がある場合は GS2-Dictionary ではエントリーの削除ができないため扱えません。 ゲームが必要とする仕様にあわせて GS2-Inventory と GS2-Dictionary を使い分ける必要があります。

GS2-Inventory との違い

スタックの概念の有無

GS2-Inventory は同一アイテムを複数所持する際に、スタックの概念があります。 これは、ポーションは最大99個スタック可能で、99個を超えると2個目のスタックを作成する というような仕様です。

この仕様があるため、GS2-Inventory では「ポーションの所持数量を取得する」というAPIの戻り値がリストになっています。 これはポーションが複数スタック存在する可能性があるためです。 この仕様はポーションのようなデータを管理するには都合がいいのですが、図鑑のようなシンプルな所持状態を管理するにはオーバースペックで、リストを取り扱うとコードの記述量も増加します。

入手処理で複数エントリーを登録可能

GS2-Inventory はポーションの入手とエリクサーの入手は別のAPIリクエストで処理する必要があります。 GS2-Dictionary は1回のAPIリクエストで最大10個のエントリーを登録できます。

お気に入り機能

GS2-Dictionary では記録済みエントリーに「お気に入り」を付与できます。AddLikesDeleteLikesResetLikes でお気に入りリストを管理し、Likes API で一覧取得や変更通知の購読が可能です。お気に入り情報を利用することで図鑑画面のフィルタリングやUIでの優先表示を実現できます。

スクリプトトリガー

ネームスペースに entryScriptduplicateEntryScript を設定すると、エントリー登録の前後や重複登録時にカスタムスクリプトを呼び出せます。スクリプトは同期・非同期の実行方式を選択でき、非同期では GS2-Script や Amazon EventBridge を利用した外部連携も可能です。

設定できる主なイベントトリガーとスクリプト設定名は以下の通りです。

  • entryScript(完了通知: entryDone): エントリー登録の前後
  • duplicateEntryScript(完了通知: duplicateEntryDone): 重複登録時の前後

実装例

図鑑への記録

図鑑への記録はゲームエンジン用の SDK では処理できません。

GS2-Quest のクリア報酬として倒したモンスターを記録する報酬を設定したり、GS2-Showcase で購入したアイテムを記録する報酬を設定することで、記録処理を行う必要があります。

図鑑に記録可能なマスターデータのリスト取得

マスターデータを登録することでマイクロサービスで利用可能なデータや振る舞いを設定できます。

マスターデータの種類には以下があります。

  • EntryModel: 図鑑に登録可能なエントリー定義

マスターデータの登録はマネージメントコンソールから登録する他、GitHubからデータを反映したり、GS2-Deployを使ってCIから登録するようなワークフローを組むことが可能です。

    var items = await gs2.Dictionary.Namespace(
        namespaceName: "namespace-0001"
    ).EntryModelsAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Dictionary->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->EntryModels(
    );
    TArray<Gs2::UE5::Dictionary::Model::FEzEntryModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

図鑑に記録されたエントリーのリスト取得

    var items = await gs2.Dictionary.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).EntriesAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Dictionary->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    );
    const auto It = Domain->Entries(
    );
    for (auto Item : *It)
    {

    }

所持証明署名の取得

GS2 内の他のマイクロサービスと連携する際に、本当に GS2-Dictionary でエントリーが記録済みか保証したデータを求められることがあります。

たとえば、GS2-Dictionary でアバターパーツの所持状態を管理しており、GS2-Formation でアバターパーツの編成状態を管理するとします。 GS2-Formation に髪型を設定する際に「hair-0001」というパーツを設定するよう APIリクエストを出すことになりますが GS2-Formation は所持証明署名をとあわせて「hair-0001」を指定するよう要求します。

これによって、GS2-Formation は裏で GS2-Dictionary と通信して、本当に所持しているパーツかを判断する必要がなくなります。

    var result = await gs2.Dictionary.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Entry(
        entryModelName: "entry-0001"
    ).GetEntryWithSignatureAsync(
        keyId: "grn:gs2:{region}:{yourOwnerId}:key:namespace-0001:key:key-0001"
    );

    var body = result.Body;
    var signature = result.Signature;
    const auto Domain = Gs2->Dictionary->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Entry(
        "entry-0001" // entryModelName
    );
    const auto Future = Domain->GetEntryWithSignature(
        "key-0001"
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError()) return false;
    const auto Result = Future2->GetTask().Result();
    const auto Body = Result->Body;
    const auto Signature = Result->Signature;

お気に入りエントリーの登録

    var domain = gs2.Dictionary.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.AddLikesAsync(
        entryModelNames: new List<string> {
            "entry-0001",
        }
    );
    const auto Domain = Gs2->Dictionary->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    );
    const auto Future = Domain->AddLikes(
        {
            "entry-0001",
        }
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

お気に入りエントリーのリスト取得

    var domain = gs2.Dictionary.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.LikesAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Dictionary->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    );
    const auto It = Domain->Likes(
    );
    for (auto Item : *It)
    {

    }

詳細なリファレンス