個人的に案件などでゲームやプログラムを作っていて基礎的な部分だが一番大事だなと思う部分が適切な状態管理です。
その状態管理について書いてみようと思います。
状態管理とは
大雑把に言えば
// ゲーム内全体のState管理用
enum GameState{
タイトル,
ゲーム,
リザルト
}
// タイトル画面内のStateの管理用
enum TitleState{
ロゴ,
オープニングアニメーション,
タイトルページ,
モード選択画面,
セーブ選択画面,
}
というようなもの
今回の例で言えば
GameStateはGame全体の状態の管理用で
TitleStateはタイトル画面での状態の管理用
という感じです。
どう使うのか
Unityでの使い方にはなりますが
他言語でも似たようなものになると思います
var m_state = TitleState.ロゴ
var m_stockState = TitleState.ロゴ
// 毎フレームの処理
private void Update() {
if(m_state != m_stockState){
OnChangeState(m_state);
}
~~ 各TitleStateでのフレーム毎処理
}
public void SetTitleState(TitleState s){
m_state = s;
}
private void OnChangeState(TitleState s){
~~ 各TitleStateでの初期化処理
m_stockState = s;
}
frameのupdateごとにStateの変化を取得する動作です
SetTitleState : 外部からStateを変更する場合のメソッド
OnChangeState : Stateが変化したときに各Stateごとの初期化処理をする部分
ちなみに SetTitleStateでそのままOnChangeStateした方がm_stockStateの変数いらなくて便利!
という人も要ると思います。
今回のコードはUnityでの作成でのコード例で
m_state
を[SerializeField]
にして、インスペクターから変更した際にも反応できるようにした形になります。
ちなみにUniRxなどの反応型のフレームワークを使う場合や、m_state
をPlay中に直接いじれないような環境は不要にはなると思います。
なぜ使うのか
これによりStateごとの初期化処理と各Update時の処理の分けることができるのと
スクリプトを見たときにかなり分け方がわかりやすいものになります。
また、デバック時に該当のステートに変更するだけでそのステートだけのテストも楽にできるようになりテストの効率も上がります。
応用など
ゲームだけに限らずライブラリを作る際などにも状態を管理する場合によく使います
Stateでクラスが現在どのような状態になっていて、その状態の場合にどのような処理をするのかというのを目で見てすぐわかるような仕組みにするには便利なので覚えて損はないはずです。
例: フェードの状態を管理するスクリプトの状態管理
enum State
{
Idle, // 透明状態
FadeOut,
FullScreen, // 全画面隠れた状態
FadeIn,
}