GS2-Showcase

商品販売機能

ゲーム内で商品を販売する際に使用します。

GS2-Exchange との違いは陳列棚が存在することです。 陳列棚には DisplayItem を陳列することができ、DisplayItem を購入するために必要な対価と、商品を購入した際に得られる報酬を設定できます。

陳列棚には2種類存在し、固定の DisplayItem が陳列される《スタンダード陳列棚》と、一定間隔で陳列内容がランダムに抽選される《ランダム陳列棚》が存在します。

スタンダード陳列棚

スタンダード陳列棚は指定した DisplayItem が全て陳列されます。 DisplayItem には2種類存在し《SalesItem》と《SalesItemGroup》が存在します。

SalesItem

SalesItem には購入するするために必要な対価と、購入した際に得られる報酬を設定できます。

SalesItemGroup

SalesItemGroup は購入回数に応じて販売する SalesItem が変化する仕組みを実現します。

SalesItemGroup には複数の SalesItem を属させることができ、リストの最後の商品以外には GS2-Limit のカウンター上昇を対価に設定する必要があります。 SalesItemGroup を陳列棚に陳列する際には、内部の SalesItem が購入可能かを判定し、一番最初に購入可能と判定された商品が陳列されます。

この機能を利用することで、初回購入のみ半額で商品を販売したり、購入するごとに価格が高くなっていく商品を実現したり、10回目の購入にはおまけをつける。というような商品を実現できます。

ランダム陳列棚

ランダム陳列棚は、マスターデータに指定した DisplayItem のうち指定した数がランダムに抽選されて陳列されます。 抽選結果は一定時間保持され、リセットタイミングを迎えるまでは同一のリストが応答されます。

リセットタイミングには1時間単位で最長7日間の間隔を指定できます。

DisplayItem ごとに《購入可能回数》と《抽選重み》を設定できます。 購入可能回数は次のリセットタイミングを迎えるまでの間にその商品を購入可能な回数を指定し、抽選重みはその商品が抽選される確率を設定します。

購入可能回数

購入APIには購入数量を指定することができますが、残り購入可能回数を上回る値を指定した場合は、1回も購入処理が行われずエラーとなります。

抽選重み

3つの商品が登録されており、以下の設定だったとします。

名前抽選重み
商品 A1
商品 B1
商品 C2

この場合、商品が抽選される確率は

名前排出確率
商品 A25%
商品 B25%
商品 C50%

となります。

もし、ランダム抽選棚が3つの商品のうち最大2つの商品を陳列する設定になっている場合、1個目の DisplayItem の抽選は上記の確率に基づきますが 2個目の DisplayItem の抽選は、すでに抽選された DisplayItem が取り除かれたリストから抽選されます。

たとえば、1個目の抽選で 《商品 C》が選択された場合、2個目の DisplayItem の抽選は以下の確率に基づきます。

名前抽選重み排出確率
商品 A150%
商品 B150%

《選出される商品の最大数》に関する注意事項

選択される商品の数を指定するフィールドの名前が《選出される商品の最大数》となっていますが、 原則、ここで指定した数値より少ない数の商品が抽選されることはありません。

例外的に《選出される商品の最大数》で指定した数より DisplayItem の設定数が少ない場合にここで指定した値より少ない商品が応答されます。

強制再抽選

各種マイクロサービスの AcquireActions に設定可能なトランザクションの報酬アクションに《ランダム陳列棚の再抽選》が用意されています。 GS2-Showcase や GS2-Exchange で《再抽選を販売》するといったマネタイズを実現することが可能です。

実装例

スタンダード陳列棚

陳列棚を取得

    var item = await gs2.Showcase.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Showcase(
        showcaseName: "showcase-0001"
    ).ModelAsync();
    const auto Domain = Gs2->Showcase->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Showcase(
        "showcase-0001" // showcaseName
    );
    const auto item = Domain.Model();

商品を購入

    var result = await gs2.Showcase.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Showcase(
        showcaseName: "showcase-0001"
    ).BuyAsync(
        displayItemId: "display-item-0001",
        quantity: 1,
    );
    const auto Domain = Gs2->Showcase->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Showcase(
        "showcase-0001" // showcaseName
    );
    const auto Future = Domain->Buy(
        "display-item-0001", // displayItemId
        nullptr, // quantity
        nullptr // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

ランダム陳列棚

陳列棚を取得

    var items = await gs2.Showcase.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).RandomShowcase(
        showcaseName: "showcase-0001"
    ).RandomDisplayItemsAsync(
    ).ToListAsync();
    const auto It = Gs2->Showcase->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->RandomShowcase(
        "showcase-0001" // showcaseName
    )->RandomDisplayItems(
    );
    TArray<Gs2::UE5::Showcase::Model::FEzRandomDisplayItemPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

商品を購入

    var result = await gs2.Showcase.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).RandomShowcase(
        showcaseName: "showcase-0001"
    ).RandomDisplayItem(
        displayItemName: "display-item-0001"
    ).RandomShowcaseBuyAsync(
        quantity: 1,
        config: null
    );
    const auto Future = Gs2->Showcase->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->RandomShowcase(
        "showcase-0001" // showcaseName
    )->RandomDisplayItem(
        "display-item-0001" // displayItemName
    )->RandomShowcaseBuy(
        1, // quantity
        nullptr // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

詳細なリファレンス