3. 冒険を開始し、報酬を受け取る
一覧に出てきた「森の探索」を、実際に遊べるようにしましょう。「開始」で冒険に出て、「クリア」で戻ってくると、10 コインがもらえるようにします。今回は何回クリアしても同じ報酬にし、初回ボーナスは付けません。
クリア報酬は GS2 側に設定する
報酬の枚数は、GS2 のクエスト設定で決めます。通常クリア報酬を「無償コイン 10 枚」にしておけば、Unity からクリアを報告したときに、GS2 がコインを加えてくれます。Unity 側では、残高の変更に合わせて画面の表示を更新します。
コインは GS2-Money2 の「ウォレット」に保存します。ウォレットを区別する番号を「スロット」と呼び、このゲームでは 0 を使います。この章で Money2 の設定を追加し、以降の章でも同じウォレットを読み書きします。
冒険の完了とコインの入金は、まとめて処理したい操作です。このような一連の処理をトランザクションと呼びます。クエストの通常クリア報酬に入金を設定すれば、Unity はクリアを報告するだけで済みます。
コインを増やすといった処理を、設定の中では「獲得アクション」と呼びます。次の手順では、通常クリア報酬にコインの獲得アクションを追加します。
手順
通貨と報酬を設定する
機能を追加 で「通貨」を追加します。
クエスト(Quest) で
forestの 通常クリア報酬 のセルをダブルクリックします。右側の アイテムを追加 を押し、追加された 未設定 を開きます。アクション で
DepositByUserIdを検索し、money2の ウォレットの残高に加算 を選びます。ターゲットリソース は なし のまま、次の値を入力します。
| 項目 | 値 |
|---|---|
| namespaceName | Currency |
| userId | #{userId} |
| slot | 0 |
#{userId} は、クリアしたプレイヤーを表す指定です。実際のプレイヤー ID に書き換えず、そのまま入力します。
- depositTransactions の 追加 を押し、作られた DepositTransaction を開きます。
priceは0、currencyは 値なし のまま、countに10を入力します。これで無償コインを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.cs:冒険の操作と画面表示
- AdventurePlayer.cs:表示用データの購読と解除
既存の 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 増えることを確認してください。
