GS2-Limit

回数制限機能

プレイヤーが行動できる回数を制限するための仕組みです。

カウンター

プレイヤーの行動回数を表現するためのエンティティで、 カウンターの値を上昇する際に許容可能な最大値を指定してカウントアップを試みることで最大値を超える場合はカウントアップが失敗し、後続の処理を失敗させることができるメカニズムで回数制限を実現します。 このとき、カウンターに対して最大値が存在するのではなく、カウントアップアクションに最大値が設定できるのが特徴です。

たとえば、スタミナの回復処理を例に考えてみます。 多くのゲームでは1日にスタミナを回復できる回数には上限が設けられています。 そして、回復をすればするほど、回復に必要な金額が上昇していきます。

このような仕様は以下のように表現できます。

ティアー回復に必要なコスト実行できる回数
Tier.1510
Tier.21010
Tier.32010
Tier.44010

そして、これを 回数制限のカウントアップアクションと、回復に必要なコストとして捉えたのが以下です。

ティアーカウンター名カウンターの上昇量カウンターの最大値回復に必要なコスト
Tier.1RecoveryStaminaCounter1105
Tier.2RecoveryStaminaCounter12010
Tier.3RecoveryStaminaCounter13020
Tier.4RecoveryStaminaCounter14040

全てのティアーで同じカウンターを使用し、回復に必要なコストが安いものほど、カウンターの最大値を低く設定しています。

こうすることで、真っ先に一番安い Tier.1 が購入できなくなり、Tier.2 を購入せざるを得なくなり Tier.2 もそのうち購入できなくなり、Tier.3 を購入せざるを得なくなるように設計ができます。

カウンターのリセット

カウンターにはリセット周期を設定可能です。 リセット周期には以下の種類が存在します。

  • リセットしない
  • 毎日 X時 にリセット
  • 毎週 X曜日 X時 にリセット
  • 毎月 X日 X時 にリセット

回数制限のリセット周期の設定は Limit Model(回数制限モデル) というマスターデータで定義します。

回数制限モデル

1つの回数制限モデル の配下に 複数のカウンターを保持することができます。 カウンターの種類はマスターデータでの定義は必要なく、カウンター操作を行う際にカウンター名を指定することで作成・使用できます。

実装例

カウンターの一覧を取得

    var items = await gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).CountersAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    );
    const auto It = Domain->Counters( // limitName
    );
    TArray<Gs2::UE5::Limit::Model::FEzCounterPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

カウンターの状態を取得

    var item = await gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    ).ModelAsync();
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Counter(
        "daily", // limitName
        "counter1" // counterName
    );
    const auto Future = Domain.Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

カウンターの値を上昇

このAPIでカウンターの上昇処理を行うことは推奨していません。 GS2-Exchange / GS2-Showcase / GS2-Quest といった回数制限を設けたい対象の処理を実行するための対価にカウンター値の上昇を設定することを推奨します。

    var result = await gs2.Limit.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        limitName: "daily",
        counterName: "counter1"
    ).CountUpAsync(
        countUpValue: 1,
        maxValue: 100
    );
    const auto Domain = Gs2->Limit->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Counter(
        "daily", // limitName
        "counter1" // counterName
    );
    const auto Future = Domain->CountUp(
        1, // countUpValue
        100 // maxValue
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Limit::Error::FOverflowError::Class))
        {
            // The maximum number of times limit has been reached.
        }
        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();

カウンターの強制リセット

カウンターの強制リセットはゲームエンジン用の SDK では処理できません。

詳細なリファレンス