天天看點

簡單通用的有限狀态機實作

簡稱狀态機(FSM),有限狀态機是為了表示有限個狀态,以及這些狀态直接的過渡行為的一個模型,在遊戲開發中,有限狀态機能夠将一個複雜的功能或者複雜的邏輯簡化為若幹個穩定的狀态,之後,在有限的狀态中切換,執行響應狀态下的功能,有限狀态機領域很廣,這裡提供一種簡單的實作。

首先做一些準備的通用工作

單例模闆類

public class Singleton<T>
    where T: class,new()
    {
        protected static T instance = null;
        public static T Instance
        {
            get
            {
                if (instance == null)
                    instance = new T();
                return instance;
            }
        }
    }
           

模闆狀态機類

public class Fsm<T>:Singleton<Fsm<T>>
    {
        public Fsm() {
        }

        protected T state;
        private Dictionary<T, List<T>> dic=null;
        protected Fsm(T state,Dictionary<T,List<T>> dis)
        {
            this.state = state;
            dic = dis;
            if (!dic.ContainsKey(state))
            {
                dic.Add(state,new List<T>());
            }
        }
        public void ChangeTo(T target)
        {
            if (dic.ContainsKey(state) && dic[state].Contains(target))
                state = target;
        }
        public void AddChange(T begin, T end)
        {
            if (!dic.ContainsKey(begin))
                dic.Add(begin, new List<T>());
            if(!dic[begin].Contains(end))
                dic[begin].Add(end);
        }
        public void RemoveChange(T begin, T end)
        {
            if (!dic.ContainsKey(begin))
                return;
            dic[begin].Remove(end);
        }
    }
}
           

現在有一個小案例,實作一個角色狀态類

接口

public interface IState
{
 	void Interact();
 	void Speak();
 }
           

若幹個狀态

public class FirState : Singleton<FirState>,IState
 {
 
 	public void Interact()
 	{
 		Debug.Log("第一種互動方式");
 	}
 
 	public void Speak()
 	{
 		Debug.Log("第一種交談方式");
 	}
 }
public class SecState : Singleton<SecState>,IState
{
	public void Interact()
	{
		Debug.Log("第二種互動方式");
	}
 
	public void Speak()
	{
		Debug.Log("第二種交談方式");
	}
}
public class ThirdState : Singleton<ThirdState>,IState
{
 
	public void Interact()
	{
		Debug.Log("第三種互動方式");
	}
 
	public void Speak()
	{
		Debug.Log("第三種交談方式");
	}
}

           

狀态機類

public class FsmState:Fsm<IState>,IState
{
	public FsmState(IState state, Dictionary<IState, List<IState>> dis) : base(state, dis)
	{
	}

	public void Attack()
	{
		state.Attack();
	}
	public void Interact()
	{
		state.Interact();
	}
	public void Speak()
	{
		state.Speak();
	}
}
           

腳本中的使用

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Game.View;

public class PlayerMove : MonoBehaviour
{
	private FsmState fsm;
	void Start () {
		var dic=new Dictionary<IState,List<IState>>();
		fsm = new FsmState(FirState.Instance as IState, dic);
		fsm.AddChange(FirState.Instance, SecState.Instance);
		fsm.AddChange(FirState.Instance, ThirdState.Instance );
		fsm.AddChange(SecState.Instance, ThirdState.Instance);
		fsm.AddChange(SecState.Instance, FirState.Instance);
		fsm.AddChange(ThirdState.Instance, FirState.Instance);
		fsm.AddChange(ThirdState.Instance, SecState.Instance);
	}
	void Update () {
		fsm.Speak();
        if (Input.GetKeyDown(KeyCode.F))
        {
	        fsm.ChangeTo(FirState.Instance);
        }
        if (Input.GetKeyDown(KeyCode.G))
        {
	        fsm.ChangeTo(SecState.Instance );
        }
        if (Input.GetKeyDown(KeyCode.H))
        {
	        fsm.ChangeTo(ThirdState.Instance);
        }
    }
}

           

總體效果

簡單通用的有限狀态機實作

這樣,按下不同按鍵後,切換狀态,人物就可以産生不同行為

以後如果再做别的狀态機,利用兩個模闆類,隻要再寫一個接口,一個狀态機類,幾個狀态類就可以輕松解決

第一次寫部落格,多多指教