3. 冒険を開始し、報酬を受け取る

冒険をクリアしたら、コインがもらえるようにします。開始から報酬の受け取りまで作ってみましょう。

一覧に出てきた「森の探索」を、実際に遊べるようにしましょう。「開始」で冒険に出て、「クリア」で戻ってくると、10 コインがもらえるようにします。今回は何回クリアしても同じ報酬にし、初回ボーナスは付けません。

クリア報酬は GS2 側に設定する

報酬の枚数は、GS2 のクエスト設定で決めます。通常クリア報酬を「無償コイン 10 枚」にしておけば、Unity からクリアを報告したときに、GS2 がコインを加えてくれます。Unity 側では、残高の変更に合わせて画面の表示を更新します。

コインは GS2-Money2 の「ウォレット」に保存します。ウォレットを区別する番号を「スロット」と呼び、このゲームでは 0 を使います。この章で Money2 の設定を追加し、以降の章でも同じウォレットを読み書きします。

冒険の完了とコインの入金は、まとめて処理したい操作です。このような一連の処理をトランザクションと呼びます。クエストの通常クリア報酬に入金を設定すれば、Unity はクリアを報告するだけで済みます。

コインを増やすといった処理を、設定の中では「獲得アクション」と呼びます。次の手順では、通常クリア報酬にコインの獲得アクションを追加します。

手順

通貨と報酬を設定する

  1. 機能を追加 で「通貨」を追加します。

  2. クエスト(Quest) で forest の 通常クリア報酬 のセルをダブルクリックします。右側の アイテムを追加 を押し、追加された 未設定 を開きます。

  3. アクション で DepositByUserId を検索し、money2 の ウォレットの残高に加算 を選びます。ターゲットリソース は なし のまま、次の値を入力します。

項目値
namespaceNameCurrency
userId#{userId}
slot0

#{userId} は、クリアしたプレイヤーを表す指定です。実際のプレイヤー ID に書き換えず、そのまま入力します。

  1. depositTransactions の 追加 を押し、作られた DepositTransaction を開きます。price は 0、currency は 値なし のまま、count に 10 を入力します。これで無償コインを10枚入金する設定になります。

通常クリア報酬の入金設定。Currency のスロット0へ、price 0・count 10 で無償コインを加える

初回クリア報酬と失敗時アクションは、0件のままにします。反映からサーバーへのデプロイと Unity プロジェクトの更新を行います。

開始・クリア・コイン表示をつなぐ

Unity の Gs2 オブジェクトに、ProgressHandler と WalletHandler を追加します。Wallet Handler の Slot は 0 です。AdventureStudioView.cs をこの章のコードに置き換え、Progress と Wallet にそれぞれ割り当てます。Quests は設定済みの QuestListHandler を使います。

冒険の操作は、次の DrawQuestButtons() にまとめています。開始ボタンから quest.Start()、クリアボタンから progress.Binder.Complete() を呼びます。Run() は処理中の連打防止とエラー表示を担当します。

残高や読み込み状態の表示は別のメソッドに分けています。全体のコードは、下のリンクからダウンロードして置き換えてください。

private void DrawQuestButtons()
{
    var canOperate = !busy && !unresolved && progress.HasValue;

    GUI.enabled = canOperate && !progress.Model.InProgress;
    foreach (var quest in quests.Binders)
    {
        GUILayout.Label(quest.DisplayName);
        if (GUILayout.Button("開始: " + quest.DisplayName))
        {
            Run(() => quest.Start());
        }
    }

    GUI.enabled = canOperate && progress.Model.InProgress;
    if (GUILayout.Button("クリア"))
    {
        Run(() => progress.Binder.Complete());
    }
    GUI.enabled = true;
}

この章の AdventureStudioView.cs をダウンロード

自分のゲームでは、敵を倒したときやゴールに着いたときに、このクリア処理を呼びます。上のコードで「クリア」ボタンに割り当てている Run(() => progress.Binder.Complete()) がその処理です。報酬は GS2 が加えるので、コインを加算するコードを別に書く必要はありません。

設定を更新する

第3章のテンプレートをダウンロードし、Deploy → adventure-game → スタックを更新を開き、テンプレートデータでダウンロードしたファイルを選びます。これは前の章のリソースも含む完全なテンプレートです。更新内容を確認して適用し、実行状態が更新完了になるまで待ちます。

通常クリア報酬の depositTransactions に、無償コインを10枚入金する設定を書きます。

action: Gs2Money2:DepositByUserId
request: |-
  {
    "namespaceName": "adventure-coin",
    "userId": "#{userId}",
    "slot": 0,
    "depositTransactions": [
      { "price": 0, "currency": "", "count": 10 }
    ]
  }

request は JSON を文字列として渡します。YAML の |- の下に JSON を書く形です。

StartAsync() で冒険を開始し、EndAsync() でクリアを報告します。それぞれが返す transaction の WaitAsync(all: true) でサーバー処理の完了を待ち、進行状況や残高の表示は、キャッシュの変更通知で更新します。

Unity のコードを更新する

次の二つのファイルを Assets に入れます。同名ファイルがある場合は置き換えてください。

既存の AdventurePlay と Inspector の Login 設定はそのまま使います。AdventurePlayer はコードから作成します。

データの変更に合わせて表示を更新する

AdventurePlayer は SubscribeWithInitialCallAsync() で初回の値と、その後の変更を受け取ります。たとえばコイン残高は、ウォレットが更新されるたびに表示用のモデルを差し替えます。

var balance = Gs2.Money2.Namespace("adventure-coin").Me(Session).Wallet(0);
var subscription = await balance.SubscribeWithInitialCallAsync(value => Wallet = value);

描画では player.Wallet.Summary.Free を参照します。進行状況も同じ方法で更新するので、開始やクリアの後に読み込み直す処理は要りません。

戻り値は購読を解除するときに使います。配布コードでは、再生を終了してオブジェクトが破棄されるときに Unsubscribe() を呼びます。

balance.Unsubscribe(subscription);

冒険を開始・クリアする

ボタンからは RunWrite() を通して開始・クリアの処理を呼びます。RunWrite() は連打防止とエラー表示を担当します。awaitingResult は要求の応答を受け取ったことを示し、その後のエラーを「要求自体が拒否された場合」と区別します。

この章で使う処理は次の部分です。抜粋を別のクラスとして追加する必要はありません。

private async UniTask BeginQuest(string questName)
{
    var transaction = await player.Gs2.Quest.Namespace("adventure-quest").Me(player.Session)
        .StartAsync("main", questName, force: false, speculativeExecute: false);
    awaitingResult = true;
    if (transaction != null) await transaction.WaitAsync(all: true);
}

private async UniTask CompleteQuest()
{
    var transaction = await player.Gs2.Quest.Namespace("adventure-quest").Me(player.Session)
        .Progress().EndAsync(isComplete: true, speculativeExecute: false);
    awaitingResult = true;
    if (transaction != null) await transaction.WaitAsync(all: true);
}

自分のゲームでは、敵を倒したときやゴールに着いたときに、この CompleteQuest() を呼びます。配布コードの「クリア」ボタンでは、RunWrite(CompleteQuest).Forget() として呼んでいます。勝利判定から呼ぶ場合も RunWrite() を通し、連打防止とエラー表示を使います。報酬は GS2 が加えるので、コインを加算するコードを別に書く必要はありません。

処理中は「開始」「クリア」ボタンを押せないようにします。返事が来る前に同じ処理を重ねて呼び出さず、成功したときに画面を切り替えます。エラーが返ったときは理由を表示してください。

冒険に出かけてみましょう

開始前のコイン残高を控えてから、冒険を始めてみてください。報酬の設定が反映されるまで最大5分かかります。変更前の枚数だった場合は、少し待ってから新しく冒険を始めて確かめます。

操作期待する結果
冒険を開始進行中の冒険が表示される
冒険をクリア冒険が終了し、コインが開始前より 10 増える
同じ冒険を新しく開始してクリアさらに 10 増える
冒険を開始せずにクリアしようとするコインは増えない

通信が途切れて結果を受け取れなかった場合は、成功とも失敗とも決めつけず「結果を確認できません」と表示します。すぐにクリア要求を送り直さないでください。

練習:設定を変えて試す

クリア報酬を 15 コインに変えて、デプロイしてみましょう。そのあとで新しく冒険を始め、クリアすると何枚増えるかを確かめてください。

ヒント

進行中の冒険には、開始時点の情報が保存されています。変更後の報酬を確かめるときは、冒険を新しく開始してください。

次の章へ進む前に

練習で変えた通常クリア報酬を 10 コインに戻してデプロイ します。同じアカウントで森の探索を新しく始めてクリアし、残高が 10 増えることを確認してください。

次へ:再起動して続きを遊ぶ