【Unity】クイズゲーム(5) 成績データのセーブとロード【クソゲー制作】

クイズゲームを作る(5)

Unity初心者がクイズゲームを作ります。

第5回は何問中何問正解したかという結果の表示画面を作ります。また、累計の成績を表示するために、成績データのセーブとロード機能も入れます。

環境
  • Mac mini (M1, 2020)
  • Unity 2022.3.36f1
目次

結果画面の表示

クイズを終了したときに最後に表示される結果画面を作ります。今回のゲームで何問中何問正解したかの正解数と正解率を表示します。

正解数をカウントする

QuizController.csに以下のコードを追加します。

public class QuizController : MonoBehaviour
{
    // ...省略...
    public int correctAnswerCount = 0; // 正解数

    // ...省略...

    // 答え合わせを遅らせるコルーチン
    IEnumerator DelayAnswer(int selectedIndex)
    {
        // ...省略...

        if (isAnswerSelected)
        {
            // 答え合わせ処理
            if (selectedIndex == correctAnswerIndex) // 正解だったら
            {
                // ...省略...
                correctAnswerCount++; // 正解数を増やす
            }
            else // 不正解だったら
            {
                // ...省略...
            }
            // ...省略...
        }
    }
}

正解数を入れておく変数correctAnswerCountを定義して、正解したら値を1増やします。

結果画面の表示

ResultController.csに以下のコードを追加します。

// ...省略...
using TMPro; // TMPを使う場合に追加
using UnityEngine.UI; // UIを使う場合に追加

public class ResultController : MonoBehaviour
{
    // ...省略...
    public TextMeshProUGUI correctNumberText; // 正解数のテキスト
    public TextMeshProUGUI correctPercentageText; // 正解率のテキスト
    public Image monkeyPortrait; // サルの肖像画のオブジェクト
    public List<Sprite> monkeyPortraitSprite; // サルの肖像画の画像リスト
    public TextMeshProUGUI resultMessage; // 結果メッセージ

    // ...省略...

    public void CreateResultPanel(int correctAnswerCount, int questionCount)
    {
        // 正解率の計算
        float correctAnswerPercentage = (float)correctAnswerCount / questionCount * 100;
        // 正解数の表示
        correctNumberText.text = $"正解数 <size=54>{correctAnswerCount}</size>/{questionCount}問";
        // 正解率の表示 (小数点以下2桁まで)
        correctPercentageText.text = $"正解率 <size=54>{correctAnswerPercentage:0.##}</size> %";
        // 正解率に応じてサルの肖像画とメッセージを変更
        if (correctAnswerPercentage >= 80)
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[0];
            resultMessage.text = $"あなたは<size=56><color=#FDD35C>チンパンジー</color></size>です";
        }
        else if (correctAnswerPercentage >= 60)
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[1];
            resultMessage.text = $"あなたは<size=56><color=#FDD35C>ボノボ</color></size>です";
        }
        else if (correctAnswerPercentage >= 40)
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[2];
            resultMessage.text = $"あなたは<size=56><color=#FDD35C>オランウータン</color></size>です";
        }
        else if (correctAnswerPercentage >= 20)
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[3];
            resultMessage.text = $"あなたは<size=56><color=#FDD35C>ゴリラ</color></size>です";
        }
        else
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[4];
            resultMessage.text = $"あなたは<size=56><color=#FDD35C>ニホンザル</color></size>です";
        }
    }
}

結果画面の内容を生成する関数CreateResultPanel()を定義しました。

19行目で正解率の計算をして、23行目で正解率の表示をしています。カスタムフォーマットを使っています。フォーマット指定子:0.##は小数点以下2桁に丸め、小数点以下の数字が0ならば表示しないという意味です。

あと、正解率に応じてサルの肖像画とメッセージを変更しています。

QuizController.csに以下のコードを追加します。

public class QuizController : MonoBehaviour
{
    // ...省略...
    public ResultController resultController; // ResultController

    // 終了ボタン
    public void FinishGame()
    {
        resultController.CreateResultPanel(correctAnswerCount, currentQuestionIndex + 1); // 結果画面を生成
        // ...省略...
    }

    // ...省略...
}

終了ボタンを押したときに、CreateResultPanel()関数を実行して結果画面を生成します。第1引数は正解数correctAnswerCount、第2引数は問題数currentQuestionIndex + 1です。currentQuestionIndex0から始まるので+ 1すると出題した問題の数になります。

成績画面の表示

タイトル画面の「成績」ボタンを押したときに表示される成績画面を作ります。成績画面には累計の正解数と正解率を表示します。つまり、過去の成績データのセーブ・ロードをする必要があります。

成績データのロードと成績画面の表示

RecordController.csに以下のコードを追加します。

// ...省略...
using TMPro; // TMPを使う場合に追加
using UnityEngine.UI; // UIを使う場合に追加

public class RecordController : MonoBehaviour
{
    // ...省略...
    public TextMeshProUGUI correctNumberText; // 正解数のテキスト
    public TextMeshProUGUI correctPercentageText; // 正解率のテキスト
    public Image monkeyPortrait; // サルの肖像画のオブジェクト
    public List<Sprite> monkeyPortraitSprite; // サルの肖像画の画像リスト
    public TextMeshProUGUI recordMessage; // 結果メッセージ

    // ...省略...

    // 成績画面生成関数
    public void CreateRecordPanel()
    {
        // データをロード
        int totalCorrectAnswerCount = PlayerPrefs.GetInt("totalCorrectAnswerCount", 0);
        int totalQuestionCount = PlayerPrefs.GetInt("totalQuestionCount", 0);

        // 正解率の計算
        float totalCorrectAnswerPercentage = totalQuestionCount == 0 ? 0 : (float)totalCorrectAnswerCount / totalQuestionCount * 100;

        // 正解数と正解率の表示
        correctNumberText.text = $"累計正解数 <size=54>{totalCorrectAnswerCount}</size>/{totalQuestionCount}問";
        correctPercentageText.text = $"累計正解率 <size=54>{totalCorrectAnswerPercentage:0.##}</size> %";

        // 正解率に応じてサルの肖像画とメッセージを変更
        if (totalQuestionCount == 0) // 解答数が0のとき
        {
            monkeyPortrait.sprite = monkeyPortraitSprite[5];
            recordMessage.text = null;
        }
        else
        {
            if (totalCorrectAnswerPercentage >= 80)
            {
                monkeyPortrait.sprite = monkeyPortraitSprite[0];
                recordMessage.text = $"あなたは<size=56><color=#FDD35C>チンパンジー</color></size>です";
            }
            else if (totalCorrectAnswerPercentage >= 60)
            {
                monkeyPortrait.sprite = monkeyPortraitSprite[1];
                recordMessage.text = $"あなたは<size=56><color=#FDD35C>ボノボ</color></size>です";
            }
            else if (totalCorrectAnswerPercentage >= 40)
            {
                monkeyPortrait.sprite = monkeyPortraitSprite[2];
                recordMessage.text = $"あなたは<size=56><color=#FDD35C>オランウータン</color></size>です";
            }
            else if (totalCorrectAnswerPercentage >= 20)
            {
                monkeyPortrait.sprite = monkeyPortraitSprite[3];
                recordMessage.text = $"あなたは<size=56><color=#FDD35C>ゴリラ</color></size>です";
            }
            else
            {
                monkeyPortrait.sprite = monkeyPortraitSprite[4];
                recordMessage.text = $"あなたは<size=56><color=#FDD35C>ニホンザル</color></size>です";
            }
        }
    }
}

21,22行目で、PlayerPrefsを使って累計の正解数と解答数をロードしています。第2引数が0なので、データが存在しない場合は0が代入されます。

24行目で正解率の計算をしています。三項演算子を使って解答数が0なら0を、それ以外なら計算結果を代入しています。このようにしないと、解答数が0の場合に正解率がNaN(非数)になってしまいます。0÷0が計算できないということですね。

TitleController.csに以下のコードを追加します。

public class TitleController : MonoBehaviour
{
    // ...省略...
    public RecordController recordController; // RecordController

    // ...省略...

    // 成績ボタン
    public void ShowRecord()
    {
        recordController.CreateRecordPanel(); // 成績画面の生成
        // ...省略...
    }

    // ...省略...
}

「成績」ボタンが押されたときにCreateRecordPanel()関数を実行して成績画面を生成します。

成績データのセーブ

ゲームを終了するときに成績をセーブする処理を実装します。

ResultController.csに以下のコードを追加します。

public class ResultController : MonoBehaviour
{
    // ...省略...

    public void CreateResultPanel(int correctAnswerCount, int questionCount)
    {
        // ...省略...

        // 累計正解数・解答数のデータをロード
        int totalCorrectAnswerCount = PlayerPrefs.GetInt("totalCorrectAnswerCount", 0);
        int totalQuestionCount = PlayerPrefs.GetInt("totalQuestionCount", 0);

        // 累計正解数・解答数に今回の正解数・解答数を足してデータをセーブ
        PlayerPrefs.SetInt("totalCorrectAnswerCount", totalCorrectAnswerCount + correctAnswerCount);
        PlayerPrefs.SetInt("totalQuestionCount", totalQuestionCount + questionCount);
    }
}

10,11行目で、累計正解数・解答数のデータをロードしています。

14,15行目で、累計正解数・解答数に今回の正解数・解答数をそれぞれ足してデータをセーブしています。

さいごに

今回も、データのセーブ・ロードにPlayerPrefsを使いましたが、そろそろ卒業したいです。定番のアセットEasy Saveを使ってみたいんだけど、高いんだよなぁ。75.90ドル!今の為替レートだと壱萬圓を超えるのよ。

セールで3000円くらいにならねぇかなぁ。

でわでわ

クイズゲームを作る(5)

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次