简单通用的有限状态机实现

简称状态机(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);
        }
    }
}

总体效果

这样,按下不同按键后,切换状态,人物就可以产生不同行为

以后如果再做别的状态机,利用两个模板类,只要再写一个接口,一个状态机类,几个状态类就可以轻松解决
第一次写博客,多多指教

发布了7 篇原创文章 · 获赞 2 · 访问量 471

猜你喜欢

转载自blog.csdn.net/qq_41815396/article/details/86367830
今日推荐