コマース

【PlayFab】スタミナ機能を実装する方法【仮想通貨を応用する】

playfab-stamina

最近のスマホゲームでは、「スタミナ」を使ったものが一般的になっています。

例えば、以下の仕様が多いのではないでしょうか。

  • クエストをするにはスタミナの消費が必要
  • スタミナは時間で少しずつ回復する
  • ジェムなどを使うと一気に回復できる

実は PlayFab では、このスタミナ機能を簡単に実装できている機能が提供されているんです。

専用の機能が用意されているわけではなく、仮想通貨の機能を応用します。

これを自前で実装しようと思うとなかなか大変なので、ありがたいですね。

この記事では、具体的な実装方法について解説しました。

コピペで使えるソースコードも用意しているので、読み終える頃には実装が完了しているはずです。

では、さっそく見ていきましょう。

スタミナ機能を実装する

スタミナ機能の出来上がりイメージを動画にしてみました。(画質が悪くすみません)

時間が0になったら、スタミナが 76 ⇒ 77 に増えていることがわかります。

動きの概要
  • 今のスタミナと最大のスタミナを表示
  • 回復までの残り時間をカウントダウン
  • 時間が0になったら、今のスタミナを1増やす

こんな感じです。

まさにスマホゲームでよく見る機能ですね。

次からは、具体的な実現方法について見ていきます。

この記事は、公式のスタミナ機能の実装サンプルを参考にしています。

仮想通貨の登録

まずは、スタミナとして使用する仮想通貨を登録していきます。

エコノミー > 通貨」と進んで、新しい通貨を登録しましょう。

playfab-stamina
ペンギンくん
ペンギンくん
リチャージレートの 288 って何?

この 288 という数字は、「1日の間にスタミナが1増えるのを、288回繰り返すことができる」という意味です。

つまり、「スタミナが1回復すると、1日の288分の1が終わる」ということですね。

さらに踏み込んで解説すると、1日は24時間で、分に直すと 24 × 60 = 1,440分です。

1,440 / 5 = 288 となるので、288は「5分に1度、スタミナが1回復する」という意味になります。

ペンギンくん
ペンギンくん
回りくどいけど理解した…

私も最初は「?」でしたが、一度理解するとあとは割り算なので、簡単ですね。

今回は最初のスタミナを50として、最大で100まで回復するよう設定しました。

最後に、「通貨を保存」のボタンを押せば設定完了です。

仮想通貨のリチャージレートを1にすれば、「24時間に1度しか回復しない仕組み」が作成できます。

これを応用することで、以下も可能になりますね。

  • ボタンを押すと、仮想通貨を消費して報酬がもらえる
  • ボタンを押せるのは、仮想通貨が1残っているときだけ
  • ボタンの表示文字は、次に押せるまでの残り時間を表示

仮想通貨は、単純にゲーム内の通貨という使い方だけではないので、いろいろと試してみてください。

プログラムの実装

実装するプログラムの全体像を見てみましょう。(ログイン処理は割愛しています)

[SerializeField] GameObject staminaBar;   // スタミナゲージ
[SerializeField] Text rechargeText;       // リチャージ時間のテキスト
DateTime nextFreeTicket = new DateTime(); // 次のリチャージ時間
bool isStaminaCapped;                     // スタミナが最大かどうか
const string VC_ST = "ST";                // スタミナの仮想通貨

private void Update()
{
    // ログインしている場合
    if (PlayFabClientAPI.IsClientLoggedIn())
    {
        // スタミナが最大ではない場合
        if (isStaminaCapped == false)
        {
            // リチャージ時間を迎えた場合はスタミナを再取得
            if (nextFreeTicket.Subtract(DateTime.Now).TotalSeconds <= 0)
            {
                rechargeText.text = "Waiting...";
                GetInventory();
            }
            else
            {
                // 残り時間をカウントダウン
                var rechargeTime = nextFreeTicket.Subtract(DateTime.Now);
                rechargeText.text = string.Format("あと {0:00}:{1:00}", rechargeTime.Minutes, rechargeTime.Seconds);
            }
        }
    }
}

void GetInventory()
{
    PlayFabClientAPI.GetUserInventory(new GetUserInventoryRequest()
    , (result) =>
    {
        result.VirtualCurrency.TryGetValue(Constants.VC_ST, out int staminaBalance);

        // スタミナリチャージ時間とリチャージ限度の取得
        if (result.VirtualCurrencyRechargeTimes.TryGetValue(Constants.VC_ST, out VirtualCurrencyRechargeTime rechargeDetails))
        {
            staminaText.text = string.Format("スタミナ({0}/{1})", staminaBalance.ToString(), rechargeDetails.RechargeMax.ToString());

            // まだリチャージ限度に達していない場合は、残り時間をカウントダウン
            if (staminaBalance < rechargeDetails.RechargeMax)
            {
                nextFreeTicket = DateTime.Now.AddSeconds(rechargeDetails.SecondsToRecharge);
                var rechargeTime = nextFreeTicket.Subtract(DateTime.Now);

                rechargeText.text = string.Format("あと {0:00}:{1:00}", rechargeTime.Minutes, rechargeTime.Seconds);
                isStaminaCapped = false;
            }
            else
            {
                rechargeText.text = string.Empty;
                isStaminaCapped = true;
            }

            // スタミナのスライダーの設定
            var slider = staminaBar.GetComponent<Slider>();
            slider.maxValue = rechargeDetails.RechargeMax;
            slider.minValue = 0f;
            slider.value = staminaBalance;
        }
    }, (error) =>
    {
        Debug.Log(error.GenerateErrorReport());
    });
}

Update メソッドについて

まずは、Update メソッドを見ていきましょう。

残り時間をリアルタイムにカウントダウンしたいので、Update メソッドで処理することが必要になります。

PlayFab にログインできていないと、API を使用することができないため、ログイン済かどうかを事前にチェックしています。

// ログインしている場合
if (PlayFabClientAPI.IsClientLoggedIn())

残り時間のカウントダウンが0になるとスタミナが1増えるので、サーバーからスタミナを再取得している、という感じですね。

// リチャージ時間を迎えた場合はスタミナを再取得
if (nextFreeTicket.Subtract(DateTime.Now).TotalSeconds <= 0)
{
    rechargeText.text = "Waiting...";
    GetInventory();
}

GetInventry メソッドについて

仮想通貨(スタミナ)を取得するには、GetInventry を呼び出す必要があります。

また、VirtualCurrencyRechargeTime というクラスの中に残り時間などの情報が入っているため、中身の取り出しをしています。

// スタミナリチャージ時間とリチャージ限度の取得
if (result.VirtualCurrencyRechargeTimes.TryGetValue(Constants.VC_ST, out VirtualCurrencyRechargeTime rechargeDetails))

あとは、今の時刻から次のスタミナ回復の時間を計算して、テキストを更新している感じですね。

最後に、スタミナのスライダーを今の値で更新したら、ひと通りの処理が完了です。

スタミナの消費や回復について

ここからは、スタミナを実際に消費したり回復したりするにはどうするか、について解説していきます。

スタミナと言っても実態は仮想通貨なので、消費や回復は仮想通貨のAPIを使用すればOKです。

スタミナを消費 Subtract User Virtual Currency
スタミナを回復 Add User Virtual Currency

上記の処理はサーバー処理となるのでご注意ください。

サーバー処理の実装については、Azure関数でCloudScriptを実行する方法をご覧ください。

クライアント側から更新することもできますが、不正が発生する可能性があるため、おすすめしません。

サーバー処理の環境構築が面倒なので、クライアント側で動作させたい!

という人のために、クライアントから動作させる設定を紹介しておきますね。

PlayFab の管理画面から「タイトルの設定 > API機能」と進むと、以下の項目が発見できます。

playfab-stamina

ここで、「クライアントに仮想通貨の加算(減算)を許可する」にチェックをつけることで、クライアントからも処理が可能になります。

また、スタミナが自動で回復するのはリチャージ限度までですが、自分で回復すれば限度を超えることが可能です。

例えば、今のスタミナが10だとして、スタミナを100回復するアイテムを使用したとしましょう。

すると、スタミナは100ではなく、110まで回復します。

ただし、リチャージ限度は超えているので、それ以上の自動回復はしない、という動きです。

ペンギンくん
ペンギンくん
超過分がなくなると寂しいから、その動きは嬉しいね!

スタミナの回復については、バンドルを使った方法が一番いいかなと思います。

合わせてチェックしてみてください。

最後に

スタミナ機能を実装する方法について解説しました。

自前で実装するとテストも大変だったりするので、仕組みが用意されているのはありがたいですね。

ロジック部分を実装するのに時間を取られて、いつまでもゲームが完成しないのはキツイです。

特に個人開発においては、「いかに実装量を減らせるか」が完成までの大きなポイントになってくると考えています。

用意されている仕組みは最大限活用して、自分の時間を生み出していきましょう。

PlayFab の書籍も好評発売中!
playfab-book

PlayFab のことをもっと皆さんに知ってもらいたくて、合計500ページ以上にもなる書籍を5冊に分けて執筆しました。

私の知識をすべて詰め込んでいるので、ゲーム開発をさらに加速させたい方はぜひご覧ください。

COMMENT

メールアドレスが公開されることはありません。