GS2-Enhance

強化機能

この機能は開発者によっては全く理解できない機能でしょう。

しかし、日本をはじめとしたモバイルゲームのデファクトスタンダードのゲームシステムには必ず存在する機能です。 このゲームメカニクス自体は Game as a Service を実現する上で有用な知識になるはずですので、理解できない開発者向けにゲームメカニズムの解説を加えます。

強化機能のゲームメカニクスについて十分な知識がある場合はこの先の解説セクションは読み飛ばして問題ありません。

強化機能のゲームメカニクス

強化機能自体は非常にシンプルなゲームシステムで、素材アイテムを消費することで、対象の経験値を加算できる仕組みです。 バトルに参加して経験値を入手するという方法だけでなく、様々な方法でキャラクターや装備の育成ができるようになっています。 (装備にもレベルがあります)

さて、このゲームシステムがなぜ Game as a Service を実現するのに一役買っているかを説明しましょう。

一言で言えば、プレイ時間の水増しで活躍しています。

開発速度よりゲームのプレイ速度のほうが圧倒的に早いのは、みなさん十分理解しているでしょう。 私たちゲーム開発者が3年間かけて開発したゲームを、プレイヤーは10時間で終えてしまうわけです。 しかし、この差を埋めないと Game as a Service は成り立ちません。 つまり、プレイヤーのコンテンツ消費速度にデバフをかける必要があります。その魔法が強化のゲームシステムです。

一般的な Game as a Service のゲームは毎月1回はイベントを実施しています。 そのイベントには、なんらかのボスが存在し、プレイヤーはそのボスをイベント期間繰り返し討伐し続けることになります。 ボスはプレイヤーの成長段階に合わせて複数の難易度を用意し、討伐することでキャラクターや装備の強化素材を手に入れることができます。

集めた強化素材を使用して、キャラクターや装備の経験値に変換し成長させます。 キャラクターや装備を成長させると、より高難易度のボスにチャレンジできるようになります。

こうすることで、プレイヤー全員がイベントに参加しつつ、自分のキャラクターの成長段階にあわせた強化素材を入手し、キャラクターや装備を成長させる遊びを楽しむことができます。

実際には、強化素材を直接ボスがドロップすることは少ないかもしれません。 代わりにイベント期間だけチャレンジできるガチャがあり、そのガチャを引くためのポイントを集めて、ガチャを経由して素材を手に入れたり イベント期間だけ開店するショップで、ボスを討伐することで得られるゲーム内通貨を集めて、ショップから強化素材を購入するなど プレイヤーの判断でどこを優先して強化するかを決定できるようにするような工夫はありますが、最終的にはプレイヤーがキャラクターの育成に必要な時間を引き伸ばしてプレイ時間を水増ししています。

イベントを通して一貫して変わらないのは、プレイヤーのキャラクターが強くなるということです。 イベントが終わると強くなったキャラクターを使用して、より高難度の恒常コンテンツを楽しむなど、次の楽しみに繋げています。

graph TD
  BossBattle["Boss Battle"] -- Acquire Event Point --> Shop
  Shop -- Buy Enhance Materials --> Enhance["Enhance Character"]
  Enhance -- More Formidable --> BossBattle

アーキテクチャ

強化には素材となるアイテムを管理している GS2-Inventory と、強化対象のキャラクターや装備を管理している GS2-Inventory または GS2-Dictionary。 そして、そのキャラクターや装備の経験値・レベルを管理している GS2-Experience を GS2-Enhance を通して操作することで実現しています。

現在の GS2 では、1回の API リクエストで消費と経験値加算を完結させる DirectEnhance による強化が推奨されています。 以前はトランザクションの自動実行機能がなかったため、大成功が出るまで通信を遮断してやり直すような行為を防ぐ目的で、準備・実行・完了報告のステップに分かれた強化プロセス(Progress)を推奨していましたが、現在はトランザクションの自動実行やアトミックコミットの仕組みが整ったため、その懸念は解消されています。

actor Player
participant "GS2-Enhance#Namespace"
participant "GS2-Inventory#ItemSet(Material)"
participant "GS2-Experience#Status"
Player -> "GS2-Enhance#Namespace" : Direct Enhance(Materials/Target Character)
"GS2-Enhance#Namespace" -> "GS2-Inventory#ItemSet(Material)" : Get experience value from metadata
"GS2-Enhance#Namespace" -> "GS2-Inventory#ItemSet(Material)" : Consume
"GS2-Enhance#Namespace" -> "GS2-Experience#Status": Add experience(Key: Target Character/Equipment Id)
"GS2-Enhance#Namespace" -> Player : Enhance result

GS2-Enhance に「強化対象」「強化に使用する素材」をパラメータとして強化実行API(DirectEnhance)を呼び出します。

すると、GS2-Enhance は素材となるアイテムのマスターデータを GS2-Inventory から取得し、メタデータ内に記録してある素材として使用した際の経験値量を取得します。 経験値量が確定したら、アイテムを消費して経験値の加算処理を GS2-Experience で実行します。

強化対象を指定していますが、GS2-Experience の経験値を管理するキーに利用するだけで、強化対象の情報を直接使用することはありません。

DirectEnhance と Progress の違い

GS2-Enhance では2種類の強化フローを提供しています。

項目 DirectEnhance Progress (Start / End)
API 呼び出し回数 1回 2回(開始・終了)
推奨用途 全ての強化処理 大成功などの抽選結果を演出に反映するため、抽選結果を先に取得しておきたい場合
アトミック性 リクエスト内で消費・経験値加算が完結 サーバーで抽選した結果を保持し、後続の End で確定
通信遮断による不正利用 発生しない 進行中の Progress は同時に1件しか保持できないため、DeleteProgress 経由でしかリトライ不可

特別な要件がない限り、 DirectEnhance の利用を推奨します。

sequenceDiagram
  participant Player
  participant Enhance as GS2-Enhance
  participant Inventory as GS2-Inventory
  participant Experience as GS2-Experience
  Player ->> Enhance: DirectEnhance(rateName, targetItemSetId, materials)
  Enhance ->> Inventory: メタデータから経験値量取得
  Enhance ->> Inventory: 素材アイテム消費
  Enhance ->> Experience: 経験値加算
  Enhance -->> Player: 加算経験値・大成功倍率

強化レート

強化に使用できる素材や、強化対象を限定するために強化レートをマスターデータとして設定する必要があります。

マスターデータには素材にできるアイテムの GS2-Inventory のネームスペース名や、インベントリ名、 強化対象にできるアイテムの GS2-Inventory のネームスペース名や、インベントリ名 といった情報を記録しています。

マスターデータは JSON 形式で管理します。

ここではItemModelのメタデータに { “experience”: 50 } のようなJSON形式で設定する例を示します。

RateModel の acquireExperienceHierarchy で JSONのキー(上記ではexperience)を定義します。 また、acquireExperienceHierarchyには階層の構造を定義できます。 例えば、{ “aaa”: { “bbb”: { “experienceValue”: 100 } } } というような構造のデータ定義でメタデータに設定したい場合は、acquireExperienceHierarchyには、[ “aaa”, “bbb”, “experienceValue” ] のように指定します。

RateModel の主な設定項目

項目 説明
name 強化レート名
targetInventoryModelId 強化対象アイテムが格納されている GS2-Inventory のインベントリモデル ID
materialInventoryModelId 強化素材アイテムが格納されている GS2-Inventory のインベントリモデル ID
acquireExperienceHierarchy 素材アイテムのメタデータから経験値量を取り出すための JSON パス
acquireExperienceSuffix 経験値モデル名のキーに付与するサフィックス(例: :level)
experienceModelId 経験値を加算する GS2-Experience の経験値モデル ID
bonusRates 大成功時の倍率と抽選重み

GS2-Enhance RateModel マスターデータ メタデータに経験値を設定する例:


{
  "version": "2020-08-22",
  "rateModels": [
    {
      "name": "enhanceRate",
      "description": "",
      "metadata": "",
      "targetInventoryModelId": "grn:gs2:ap-northeast-1:YourOwnerId:inventory:enhance-inventory:model:character",
      "acquireExperienceSuffix": ":level",
      "materialInventoryModelId": "grn:gs2:ap-northeast-1:YourOwnerId:inventory:enhance-inventory:model:material",
      "acquireExperienceHierarchy": [
        "experience"
      ],
      "experienceModelId": "grn:gs2:ap-northeast-1:YourOwnerId:experience:enhance-experience:model:character",
      "bonusRates": [
        {
          "rate": 2,
          "weight": 1
        },
        {
          "rate": 1,
          "weight": 1
        }
      ]
    }
  ]
}

bonusRates には複数のエントリーを設定でき、各エントリーは抽選重み(weight)と倍率(rate)を持ちます。 上記の例では「2倍経験値」と「等倍経験値」が同じ重みで抽選され、おおよそ50%の確率で大成功(2倍)が発生します。

GS2-Experience ExperienceModel マスターデータ例:

{
  "version": "2019-01-11",
  "experienceModels": [
    {
      "name": "character",
      "metadata": "CHARACTER",
      "defaultExperience": 0,
      "defaultRankCap": 50,
      "maxRankCap": 80,
      "rankThreshold": {
        "metadata": "RANK_THRESHOLD",
        "values": [
          100,
          300,
          500,
          1000
        ]
      }
    }
  ]
}

GS2-Inventory ItemModel マスターデータ メタデータに経験値を設定する例:

{
  "version": "2019-02-05",
  "inventoryModels": [
    {
      "name": "character",
      "initialCapacity": 1,
      "maxCapacity": 1,
      "protectReferencedItem": false,
      "itemModels": [
        {
          "name": "character-0001",
          "stackingLimit": 1,
          "allowMultipleStacks": false,
          "sortValue": 0
        }
      ]
    },
    {
      "name": "material",
      "metadata": "",
      "initialCapacity": 10,
      "maxCapacity": 10,
      "protectReferencedItem": false,
      "itemModels": [
        {
          "name": "material-0001",
          "metadata": "{\"experience\":50}",
          "stackingLimit": 99,
          "allowMultipleStacks": false,
          "sortValue": 0
        }
      ]
    }
  ]
}

限界突破 (Unleash)

同種のアイテムなどを素材として消費し、対象のレベル上限を引き上げる「限界突破」機能も提供しています。 GS2-Grade が管理するグレードを 1 つ引き上げ、それに連動して GS2-Experience の rankCap(ランク上限)を引き上げる仕組みで、UnleashRateModel のマスターデータで以下を設定します。

  • 限界突破対象のインベントリモデル(targetInventoryModelId)
  • 紐づくグレードモデル(GS2-Grade の gradeModelId)
  • 各グレードに到達するために必要な素材(gradeEntries)

これにより「同じキャラクターを4体集めると限界突破できる」「同じ部位の装備か専用素材のどちらかを消費して装備を合成する」といったゲームメカニクスを実装できます。

gradeEntries の各エントリの gradeValue は、限界突破で到達するグレードです。対象の現在のグレードが 2 なら、gradeValue が 3 のエントリの条件が使われます。 GS2-Grade のグレードは 1 始まりです(どの defaultGrades にも当てはまらない対象はグレード 1 から始まります)。

素材条件の種類

エントリごとに type で素材条件の書き方を選びます。グレードごとに混ぜて使えます。

type 説明
simple(既定) 対象と同種のアイテムを needCount 個消費します。素材は実行時に materials でアイテムセットを指定します。同種かどうかは GS2-Grade の gradeUpPropertyIdRegex で判定します。
recipe recipes に定義した複数のレシピから、プレイヤーが 1 つを選んで実行します。選んだレシピの素材はすべて消費されます。

レシピ

レシピの素材は、どう消費するかを materialType で選び、種類ごとの設定を持ちます。

materialType 消費のしかた 設定
individual プレイヤーが選んだアイテムセット(装備の複製など)を 1 個ずつ消費します。素材は対象と同じインベントリモデルに属している必要があります。 individualSetting
quantity 設定で決まるアイテム(汎用強化素材など)を数量で消費します。プレイヤーはアイテムを選びません。通常のインベントリとシンプルインベントリの両方を使えます。 quantitySetting

individualSetting の項目は次のとおりです。

項目 説明
matchType sameItem: 対象と同じアイテムモデルのみ。sameGroup: 対象と同じグループキーを持つアイテムモデル。
gradeCondition any: 素材のグレードを問わない。sameAsTarget: 素材のグレードが対象の現在のグレードと同じ。equal: 素材のグレードが gradeValue と同じ。素材のグレードはトランザクションの中で GS2-Grade により検証されます。
count 消費するアイテムセットの数

quantitySetting の項目は次のとおりです。

項目 説明
matchType specified: itemModelId で指定したアイテムを消費。sameGroup: materialInventoryModelId のインベントリの中で、対象と同じグループキーを持つアイテムを消費(該当するアイテムモデルはちょうど 1 つである必要があります)。
itemModelId / materialInventoryModelId 消費するアイテムモデル / 素材を探すインベントリモデル。シンプルインベントリの GRN も指定できます。
count 消費する数量

レシピの targetGroupKeys を指定すると、対象のグループキーがその中に含まれるときだけ、そのレシピを使えます。空の場合はどの対象にも使えます。

グループキー

「同じ部位」のような分類は、アイテムモデルのメタデータ(JSON)に書いたグループキーで表します。 UnleashRateModel の groupKeyHierarchy で、メタデータのどの階層にグループキーがあるかを指定します。値は文字列である必要があります。

例えば、アイテムモデルのメタデータが次のようになっている場合は、groupKeyHierarchy に ["unleash", "group"] を指定します。

{ "unleash": { "group": "weapon" } }

部位別の汎用素材のアイテムモデルにも同じ形でグループキーを書いておくと、quantitySetting の sameGroup で「対象と同じ部位の汎用素材」を 1 つのレシピで表せます。

マスターデータの例

装備をグレード 2 にするには同じ装備を 1 つ、グレード 3 にするには同じ部位の装備(グレード 1)か部位別の汎用素材 2 個のどちらかを消費する例です。

{
  "name": "equipment",
  "targetInventoryModelId": "grn:gs2:{region}:{ownerId}:inventory:namespace-0001:model:equipment",
  "gradeModelId": "grn:gs2:{region}:{ownerId}:grade:namespace-0001:model:equipment",
  "groupKeyHierarchy": ["unleash", "group"],
  "gradeEntries": [
    {
      "gradeValue": 2,
      "type": "recipe",
      "recipes": [
        {
          "name": "merge",
          "materials": [
            {
              "name": "same",
              "materialType": "individual",
              "individualSetting": { "matchType": "sameItem", "gradeCondition": "sameAsTarget", "count": 1 }
            }
          ]
        }
      ]
    },
    {
      "gradeValue": 3,
      "type": "recipe",
      "recipes": [
        {
          "name": "fodder",
          "materials": [
            {
              "name": "fodder",
              "materialType": "individual",
              "individualSetting": { "matchType": "sameGroup", "gradeCondition": "equal", "gradeValue": 1, "count": 1 }
            }
          ]
        },
        {
          "name": "material",
          "targetGroupKeys": ["weapon", "armor"],
          "materials": [
            {
              "name": "material",
              "materialType": "quantity",
              "quantitySetting": {
                "matchType": "sameGroup",
                "materialInventoryModelId": "grn:gs2:{region}:{ownerId}:inventory:namespace-0001:simple:model:unleash-material",
                "count": 2
              }
            }
          ]
        }
      ]
    }
  ]
}

実行時の指定

type が recipe のエントリでは、限界突破の実行時に recipeName でレシピを指定し、recipeMaterials で individual の素材ごとに消費するアイテムセットを指定します。quantity の素材は指定不要です。

{
  "targetItemSetId": "grn:...:item:sword-0001:itemSet:target",
  "recipeName": "merge",
  "recipeMaterials": [
    { "name": "same", "itemSetIds": ["grn:...:item:sword-0001:itemSet:material"] }
  ]
}

次の場合はトランザクションを発行する前にエラーになります。

  • 素材に対象自身が含まれている、または同じアイテムセットが重複している
  • 素材の数がレシピの count と一致しない、レシピにない素材名を指定している
  • 素材が対象と別のインベントリモデルに属している、matchType の条件に一致しない
  • targetGroupKeys に対象のグループキーが含まれない、対象のグループキーをメタデータから取得できない
  • quantitySetting の sameGroup で該当するアイテムモデルが 0 個、または 2 個以上ある

素材として消費したアイテムセットが持っていた経験値やグレードは、対象へは引き継がれません。

スクリプトトリガー

ネームスペースに enhanceScript を設定すると強化実行の前後でカスタムスクリプトを呼び出せます。処理の許可・否認や入手経験値の上書きが可能で、実行方式は同期・非同期を選択できます。非同期では GS2-Script や Amazon EventBridge を利用した外部連携にも対応します。

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

  • enhanceScript(完了通知: enhanceDone): 強化実行の前後

スクリプト内では強化対象・素材アイテム・抽選される倍率を参照でき、ゲームバランス調整やイベント期間中のブースト倍率変更といった用途で活用できます。

マスターデータ運用

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

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

  • RateModel: 強化素材や対象の定義
  • UnleashRateModel: 上限解放用のレート定義

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

トランザクションアクション

GS2-Enhance では以下のトランザクションアクションを提供しています。

  • 消費アクション: 実行中の強化進行情報(Progress)の削除
  • 入手アクション: 即時強化(DirectEnhance)の実行、限界突破(Unleash)の実行、強化(Progress)の開始

「即時強化(DirectEnhance)の実行」を入手アクションとして利用することで、特定のクエストクリア報酬やショップでのアイテム購入時の報酬として、直接キャラクターや装備に経験値を付与するといった処理が可能になります。また、「限界突破(Unleash)」を報酬として設定することで、特定のミッション達成時に自動的にレベル上限を引き上げるといった運用も可能です。

実装例

強化レート一覧の取得

    var items = await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).RateModelsAsync(
    ).ToListAsync();
    const auto It = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->RateModels();
    TArray<Gs2::UE5::Enhance::Model::FEzRateModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
var iterator = ez.enhance.namespace_(
        "namespace-0001"
    ).rate_models(
    )

var async_result = await iterator.load()
if async_result.error != null:
    # エラーを処理
    push_error(str(async_result.error))
    return

var items = async_result.result

強化の実行(DirectEnhance)

materials には消費する素材アイテムの ItemSetId と数量を指定します。 強化対象として targetItemSetId に強化したいキャラクター・装備の ItemSetId を渡します。

    var result = await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Enhance(
    ).EnhanceAsync(
        rateName: "rate-0001",
        targetItemSetId: "item-set-0001",
        materials: new [] {
            new Gs2.Unity.Gs2Enhance.Model.EzMaterial
            {
                MaterialItemSetId = "material-0001",
                Count = 1,
            },
        }
    );

    var transaction = result;
    await transaction.WaitAsync();
    const auto Domain = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Enhance(
    );
    const auto Future = Domain->Enhance(
        "rate-0001",
        "item-set-0001",
        []
        {
            const auto v = MakeShared<TArray<TSharedPtr<Gs2::Enhance::Model::FMaterial>>>();
            v->Add(MakeShared<Gs2::Enhance::Model::FMaterial>()
                ->WithMaterialItemSetId(TOptional<FString>("material-0001"))
                ->WithCount(TOptional<int32>(1)));
            return v;
        }()
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

    const auto Transaction = Future->GetTask().Result();
    const auto Future2 = Transaction->Wait();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError()) return false;
var domain = ez.enhance.namespace_(
        "namespace-0001"
    ).me(game_session).enhance(
    )

var async_result = await domain.enhance(
    "rate-0001", # rate_name
    "item-set-0001", # target_item_set_id
    [
        Gs2EnhanceEzMaterial.new()
            .with_material_item_set_id("material-0001")
            .with_count(1),
    ], # materials
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

強化(Progress)の開始

抽選結果を先に取得しておきたい場合のフローです。 進行中の Progress は1ユーザーあたり1件のみ保持できます。

    var result = await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    ).StartAsync(
        rateName: "rate-0001",
        targetItemSetId: "item-set-0001",
        materials: new [] {
            new Gs2.Unity.Gs2Enhance.Model.EzMaterial
            {
                MaterialItemSetId = "material-0001",
                Count = 1,
            },
        }
    );
    const auto Future = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Progress(
    )->Start(
        "rate-0001", // rateName
        "item-set-0001", // targetItemSetId
        []
        {
            const auto v = MakeShared<TArray<TSharedPtr<Gs2::Enhance::Model::FMaterial>>>();
            v->Add(MakeShared<Gs2::Enhance::Model::FMaterial>()
                ->WithMaterialItemSetId(TOptional<FString>("material-0001"))
                ->WithCount(TOptional<int32>(1)));
            return v;
        }()
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
var domain = ez.enhance.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

var async_result = await domain.start(
    "character-level", # rate_name
    "item-set-0001", # target_item_set_id
    [
        Gs2EnhanceEzMaterial.new()
            .with_material_item_set_id("material-0001")
            .with_count(1),
    ], # materials
    null, # force
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

進行中の強化情報を取得

抽選済みの倍率(大成功フラグ)や入手経験値量を取得し、強化演出に活用できます。

    var item = await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    ).ModelAsync();

    var experienceValue = item.ExperienceValue;
    var rate = item.Rate;
    const auto Domain = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Progress(
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

    const auto Result = Future->GetTask().Result();
    const auto ExperienceValue = Result->GetExperienceValue();
    const auto Rate = Result->GetRate();
var domain = ez.enhance.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

強化(Progress)の完了

Start で開始した強化を End で確定し、消費・経験値加算を実行します。

    var result = await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    ).EndAsync();

    await result.WaitAsync();
    const auto Future = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Progress(
    )->End();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

    const auto Transaction = Future->GetTask().Result();
    const auto Future2 = Transaction->Wait();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError()) return false;
var domain = ez.enhance.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

var async_result = await domain.end(
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

進行中の強化情報を破棄

通信が途切れて完了報告が行えなくなった場合などのリカバリーに使用します。

    await gs2.Enhance.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Progress(
    ).DeleteProgressAsync();
    const auto Future = Gs2->Enhance->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Progress(
    )->DeleteProgress();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;
var domain = ez.enhance.namespace_(
        "namespace-0001"
    ).me(game_session).progress(
    )

var async_result = await domain.delete_progress(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

その他の機能

強化の大成功

強化の仕様として、一定確率で「大成功」が発生し、入手できる経験値量が 1.5倍 や 2倍になる仕様があることがあります。 GS2-Enhance では強化レートとして、大成功が発生する確率とその場合の経験値の獲得量の倍率を設定できます。

bonusRates の weight の合計値に対する各エントリーの weight の割合が、その倍率の発生確率となります。

Config を使用したスクリプトへのパラメータ受け渡し

EnhanceAsync / StartAsync には config パラメータを指定でき、スクリプトトリガー実行時に任意のキーと値のペアを渡せます。 ゲーム内のイベントブースト状態や、プレイヤーが選択した強化モードといった情報をスクリプトに伝えることができます。

投機的実行(Speculative Execute)

speculativeExecute 引数(デフォルト true)を有効にすると、API リクエストの応答を待つ前にクライアント側のキャッシュを更新し、UI 上では即座に経験値加算後の状態を表示できます。 通信遅延の影響を受けにくいテンポの良い操作感を実現できます。

詳細なリファレンス