前回までの作業で、ゲーム内容的にはほぼ完成と言っても遜色ないレベルになりました。しかし、まだもう少しやるべきことがあります。それはハイスコアの保存です。
今はまだセーブ処理を作っていないので、一旦ゲームを閉じるとハイスコアの記録が消えてしまいます。そこでここでは最初に導入してもらった「くろくま基本アセット」のセーブ管理クラス(SaveManager)を使って、ハイスコアを保存したり読み込んだりする処理を作りましょう。
※2020年2月27日現在、WebGLでビルドした場合にハイスコアが保存されない場合があるバグが確認されています(エディタ上では問題なく動作します)。あらかじめご承知おきください。
セーブ管理クラス「SaveManager」の概要
では、まず初めに「くろくま基本アセット」に含まれているセーブ管理クラス「SaveManager」(※)の概要を説明します。一言でいうと、今回使うSaveManagerではPlayerPrefsを使わない方法でセーブ・ロード処理を行います。
セーブ機能と言えば、よくUnityの入門書等では「PlayerPrefsを使いましょう」的なことが書かれているのを目にしたことがある方も多いのではないでしょうか。しかし、PlayerPrefsは不便だし問題も多い機能なので、本格的にゲームを作るならPlayerPrefsは使うべきではないと私は思っています。
そこで、SaveManagerではデータを「JSON」という形式のファイルで出力して管理する方法を採用しました。この辺についての詳しい話は中級レベルになるのでここでは省きますが、処理内容を知りたいという方は「コインを集めて!ユニティちゃん」のページ「PlayerPrefsを使わないセーブ・ロード処理の作り方」をご覧いただければと思います。
※なおSaveManagerはUnityに最初からあるクラスではなく、私が勝手に作ったクラスなので勘違いに注意してください。
セーブ機能を使えるようにするまでの手順
ただまあ、概要を書いたところで「なんかよく分からん」という方も多いかと思いますので、実際の作業を通してSaveManager使い方を説明します。主な作業手順は次の通りです。
- SaveDataクラスを変更する
- SaveManagerを変更する
- GameManagerからセーブ機能を呼び出す
SaveDataクラスの変更
まず、「くろくま基本アセット」のセーブ機能では「SaveData」というクラスに保存したいデータを格納する必要があります。デフォルトでは音量設定だけが書かれているので、そこにハイスコアを保存するための変数を追加しましょう(下記)。
[System.Serializable] public class SaveData { public float volume = 1.0f; public float bgmVolume = 0.3f; public float seVolume = 0.6f; public int highScore = 0; //追加 }
SaveManagerの変更
次にSaveManagerに、先ほどSaveDataに追加した変数を読み書きするためのプロパティを追加します。また、デフォルトだとデバッグ実行時はセーブデータの読み書きをしないようになっているので、その部分も書き換えておきます(※下記。無関係なところは省略してあるので注意)。
//省略 public float SeVolume { set { save.seVolume = value; } get { return save.seVolume; } } //追加 public int HighScore { set { save.highScore = value; } get { return save.highScore; } } protected override void Awake() { base.Awake(); string saveFileName = "saveData"; if (Debug.isDebugBuild) { saveFileName += "_test"; } filePath = Application.persistentDataPath + "/" + saveFileName + ".json"; save = new SaveData(); moveSceneManager = GetComponent<MoveSceneManager>(); //変更 if (File.Exists(filePath)) { Load(); } else { Save(); } } //省略
GameManagerの変更
最後に、またしてもGameManagerを変更する必要があります。InitGameメソッドとGameOverメソッドを次のように書き換えてください(※「追加その5」という部分が変更箇所です)。
//省略 //--ここから追加-- public void InitGame() { gameStarted = false; //追加その3 level = 1; mileage = 0; maxScore = (int)Mathf.Pow(10, scoreDigits) - 1; //スコアの最大値を作成。例えば、8桁なら99999999 score = 0; timerIsActive = false; //追加その3 wallSpawner.isActive = false; //追加その3 wallSpawner.InitSpawner(); //追加その3 coinSpawner.isActive = false; //追加その4 coinSpawner.InitSpawner(); //追加その4 highScore = saveManager.HighScore; //追加その5 //追加その3。UI表示の初期化 UpdateMileageUi(); UpdateLevelUi(); UpdateScoreUi(); } //省略 public void GameOver() { if(playerObj != null) { Destroy(playerObj); } gameStarted = false; //追加その3 timerIsActive = false; wallSpawner.isActive = false; gameOverCanvas.enabled = true; retryButton.enabled = true; //追加その3 coinSpawner.isActive = false; //追加その4 //追加その5 if (highScore > saveManager.HighScore) { saveManager.HighScore = highScore; saveManager.Save(); } } //省略
SaveManager経由でハイスコアの読み込み・書き込みやセーブを行えるようにしました。
さて、これでハイスコアの保存ができるはずです。一回ゲームオーバーになるまでゲームを実行して一度終了し、もう一度再生したときにきちんとハイスコアが反映されていれば成功です。