【Unity実践】#22 ステージ管理の仕組みを作成【ランゲーム】
今回の内容
今回はステージ管理の仕組みを作成します。
本連載中で最も難しい内容かもしれません。
※初めての方はこちらから
⇒ 【第1回記事】導入とサンプルの紹介
仕様とデータの整理
ステージ管理の仕組みはゲームの仕様や開発プロジェクトによって様々です。
ここでは、仕様を決めて実装をしていきます。
<仕様>
・最初にロードするステージは名前が「Stage1」のシーン
・クリアごとに「Stage〇〇」の名前のシーンを順にロード(〇〇は数字が入る)
・全ステージクリア後は、ランダムにステージが読み込まれる
・現在何ステージ目かを「Level」という単位で管理する。(画面上部に表示)
次に、セーブデータとして管理する項目を整理します。
セーブデータと言いましたが、Unityの標準機能にある PlayerPrefs のことです。
上記仕様をもとに、以下の2つのパラメータを用意します。
・levelNum → 現在何ステージ目か
・stageNum → 読み込むステージの番号(Stage〇〇の〇〇に入る数字)
全ステージクリアするまでは stageNum と levelNum は一致しますが、
クリア後は stageNum はランダム、levelNum は引き続き1ずつ増加していきます。
前回までに作成した coinNum と併せて、PlayerPrefs は以下のような構成となります。
coinNum を除く2つのデータの役割を理解しておかないと、以降の実装が分からなくなるので、必ず頭に入れてから読み進めてください。
フロー図を考える
次に処理フローを考えていきます。
ここでは一例として以下に載せたものを使用します。
このフロー図に従って、次はいよいよ実装をしていきます。
余裕のある方は一度自分で実装してみて頂いても良いと思います。
実装してみる
GameManagerScript を編集していきます。
① プロパティを追加する
~ 省略 ~ public class GameManagerScript : MonoBehaviour { public enum GAME_STATUS { Play, Clear, Pause, GameOver }; public static GAME_STATUS status; public static int tempCoinNum; [SerializeField] Text coinNumText, resultCoinText, levelNumText; [SerializeField] GameObject clearUI, gameOverUI; int stageCoinNum; const string STAGE_NAME_PREFIX = "Stage"; const int MAX_STAGE_NUM = 1; int levelNum; // 現在の進行数 int stageNum; // 読み込むステージ番号 void Start() { ~ 省略 ~
11行目は、levelNumText のみ追加しています。
STAGE_NAME_PREFIX は読み込むシーン名の数字を抜いた文字列を設定します。
MAX_STAGE_NUM にはステージ数を設定します。
② ロード対象のシーンをロードするメソッドを作成
以下の2つのメソッドを追加してください。
private string GetLoadSceneName() { return STAGE_NAME_PREFIX + stageNum; } public void LoadScene() { SceneManager.LoadScene(GetLoadSceneName()); }
GetLoadSceneName は読み込むべきシーンの名前を取得するメソッドです。
実際の読み込みは LoadScene メソッドで行っており、ステージ名の取得に GetLoadSceneName を使用しています。
③ LoadNextSceneメソッドを変更
以前作成した、LoadNextSceneメソッドを下記の通り変更します。
public void LoadNextScene() { PlayerPrefs.SetInt("levelNum", ++levelNum); stageNum = levelNum <= MAX_STAGE_NUM ? levelNum : Random.Range(1, MAX_STAGE_NUM + 1); PlayerPrefs.SetInt("stageNum", stageNum); LoadScene(); }
これはクリア画面のNextボタンで呼び出していたメソッドです。
処理内容は、フロー図のクリア以降の流れに従っています。
※Random.Rangeの第二引数について
Random.Range(A, B) は「A以上B未満の乱数」を生成します。
そのため「MAX_STAGE_NUM + 1」とすることで、「1~MAX_STAGE_NUMの乱数」を生成します。
ただしこれは引数が整数の場合で、小数を指定した場合とは異なるので注意してください。
(公式リファレンス)Random.Range
④ Startメソッドを変更
最後に、Startメソッドを変更します。
void Start() { // ステージ番号ロード stageNum = PlayerPrefs.GetInt("stageNum", 1); // 自分のシーンではない場合、ロードし直す if (!GetLoadSceneName().Equals(SceneManager.GetActiveScene().name)) { LoadScene(); return; } // レベル番号をロード levelNum = PlayerPrefs.GetInt("levelNum", 1); levelNumText.text = "Level " + levelNum; // ステージ内のコインの枚数を取得 stageCoinNum = GameObject.FindGameObjectsWithTag("Coin").Length; // これまでの獲得コイン数をロード(初回は0) tempCoinNum = PlayerPrefs.GetInt("coinNum", 0); // ステータスをPlayに status = GAME_STATUS.Play; }
処理内容は、フロー図のゲームプレイ前の内容となっています。
この処理の目的は、ゲームを再起動した時に最初のシーン(Stage1)が読み込まれてしまう問題の対策です。
PlayerPrefs を参照して続きのシーンを再読み込みさせる形としています。
また、フロー図には無いですが levelNum を UI に反映する処理を記述しています。
levelNumText には以下のUIオブジェクトを忘れずに設定してください。
Canvas > GameUI > LevelNumText
ここまででステージ管理の仕組みは完成となります。
動作確認と完成版コード
テストプレイは以下の準備を済ませた上で行ってください。
<テストプレイ準備>
・Stage1を複製して少し変更を加えたシーンを複数用意
・複製した分だけ、MAX_STAGE_NUMの値を変更
・Build Settings を開いて、Stage〇〇を追加
※3つ目のBuild Settings の設定イメージは下記です。
設定方法は割愛しますので、以下の記事の「ビルドの設定」を参照してください。
【初心者Unity】シーンの切り替え
また、コードの最終形を以下に載せておきます。
おわりに
かなり難しい内容でしたが、ステージ管理の仕組みは多くのゲームで必要となります。
実装方法は様々ですので、自分で仕様を変えてカスタマイズしてみても良いかと思います。
関連リンク ➡ 「初心者のための」Unityゲーム制作 目次
© Unity Technologies Japan/UCL