【Unity】ピュアC#なステートマシン「ImtStateMachine」を導入する

DEVELOP, Unity

ゲームの進行管理は状態遷移の塊の様なもの。ゲーム開発はこれからという場合、まずはステートマシンを導入するところから始めてみると良いかもしれません。

コルーチンの悪夢

Unityで開発していると、便利さ故に処理をついコルーチンぶっ放しなコーディングをしてしまいがち。事実、管理されないコルーチンまみれなプロジェクトがあったりしてデバッグが困難。デバッガーなしのテキストエディタレベルでプログラムを追うことが出来る方なら良いのですが、それってチーム開発だとあまり優しくない。このコードって今どのタイミングで呼ばれたものなんだろう?ってなってしまう。開発者が状態を把握し辛いのも厳しい。

なぜ状態遷移が欲しいのか?

デバッグが容易(コールスタックで追える)

ほんとこれ。スコープを絞れるとかもありますけど。余裕の無いプロジェクトほど蔑ろにされますが、これだけで開発効率って変わります。バグは発生するものなので、いかに素早く解決できる作りにしているのか?が重要なのです。

ステートマシンの導入

ステートマシンって、書き方は定石があるので1から組んでも良いのですが、既に素晴らしいピュアC#なものが公開されていましたので有難く使わせて頂きましょう。作成者様様です。

ImtStateMachine

ImtStateMachineを使った簡単なサンプルプロジェクト

欲しいファイルは、

Assets/Plugins/ImtStateMachine.cs

これひとつ。使用するUnityプロジェクトに持っていくだけで使えます。

使い方

using IceMilkTea.Core;

名前空間を宣言し

public class SceneBase : MonoBehaviour
{
    private enum StateEventId
    {
        Idle,
        Init,
    }

    // ステートマシン
    private ImtStateMachine<SceneBase> stateMachine;

    private void Awake()
    {
        // ステートマシンの遷移テーブルを構築
        stateMachine = new ImtStateMachine<SceneBase>(this);
        stateMachine.AddTransition<IdleState, InitState>((int)StateEventId.Init);
        stateMachine.AddTransition<InitState, IdleState>((int)StateEventId.Idle);

        // 開始ステートの設定
        stateMachine.SetStartState<InitState>();
        // 即ステートを実行したい場合はUpdateを呼ぶ
        stateMachine.Update();
    }

    /// アイドリング中ステート
    private class IdleState : ImtStateMachine<SceneBase>.State
    {
    }

    /// 初期化ステート
    private class InitState : ImtStateMachine<SceneBase>.State
    {
        protected internal override void Enter()
        {
        }

        protected internal override void Update()
        {
            // 初期化が完了したIdleステートへ遷移
            Context.stateMachine.SendEvent((int)StateEventId.Idle);

        }

        protected internal override void Exit()
        {
        }
    }

}

ポイントは遷移先の小さなクラスを作って、AddTransitionによる状態遷移図を構築すること。遷移の切り替えはSendEventで行える。シンプルで素晴らしい。

Posted by kazupon