俺のプログラムの大部分はステートマシンで表現されている

こんにちは。ヤマヤタケシです。
プログラミングやってます。

ステートマシンというちょっと大げさな言葉があります。
FSMと略したりします。
日本語で言うと「状態機械」です。

ステートマシンをうまく使うと色々すっきり書けます。
ステートマシンを使わない場合は、フラグをつかう事になります。
とか、昔もこのブログで書いたことあるきがしてきました。
まあ、Unityをつかうようになってもステートマシンは手放せないんです。

オレオレステートマシンというのは、1ステート=3メソッドと、Update, Changeで作られています。
状態を変化させると、終了、初期化、が呼ばれます。
中途半端な隙がありません。
まあ、大したコードではない割に便利なので、ここに公開します。

//
//
// StateMachien for Unity
//
using System;
using System.Collections.Generic;
using UnityEngine;

public class StateMachine
{
    class State
    {
        public State(T tag, Action init, Action exit, Action update)
        {
            this.Tag = tag;
            this.Init = init;
            this.Exit = exit;
            this.Update = update;
        }
        public T Tag;
        public Action Init;
        public Action Exit;
        public Action Update;
    }
    Dictionary stateList; 
    State now;

    public StateMachine()
    {
        stateList = new Dictionary();
    }


    public void Add( T tag, Action init, Action exit, Action update )
    {
        stateList.Add(tag, new State( tag : tag, init : init, exit : exit, update: update) );
    }


    public void Change(T tag)
    {
        if( now != null)
        {
            if( now.Exit != null )
            {
                now.Exit();
            }
            now = null;
        }
        now = stateList[tag];

        if( now != null)
        {
            if (now.Init != null)
            {
                now.Init();
            }
        }
    }

    public void Update()
    {
        if( now == null)
        {
            return;
        }
        if( now.Update != null )
        {
            now.Update();
        }
    }
}

クラスAはWait状態とLaser状態があります。
ステートマシンに登録して、切り替えます。

//
class A
{
    enum StateTag
    {
        Wait,
        Laser,
    }
    StateMachine state;


    void Start ()
    {
        StateMachine state = new StateMachine();
        {
            state.Add( StateTag.Wait, WaitInit, WaitExit, WaitUpdate );
            state.Add( StateTag.Laser, LaserInit, LaserExit, LaserUpdate );
        }
        state.Change(StateTag.Wait);
	}


    void Update ()
    {
        state.Update();
    }

    // Wait
    void WaitInit(){}
    void WaitExit(){} 
    void WaitUpdate()
    {
        if( Input.GetMouseButton(0))
        {
            state.Change(StateTag.Laser);
        }
    }

    // Laser
    void LaserInit() { }
    void LaserExit(){} 
    void LaserUpdate()
    {
        if( Input.GetMouseButton(0))
        {
        }
        else
        {
            //終了
            state.Change(StateTag.Wait);
        }
    }

}

そんじゃまた。

コメントを残す