这两天一直没做多少毕设的东西,只是简单的实现了下fsm状态机,之前只是了解并没有彻底接触过,学习了一下发现并没有想象中那么复杂,于是根据一篇教程自己改动了下。状态机果然好用,把逻辑简化了很多,虽然代码量多了很多。原贴地址:https://blog.csdn.net/code_sheen/article/details/45869505
IState:
public interface IState { /// <summary> /// 获取状态ID /// </summary> /// <returns></returns> int GetStateID(); /// <summary> /// 进入状态回调此方法 /// </summary> /// <param name="stateMachine">控制此状态的状态机</param> /// <param name="prevState">进入此状态的前状态</param> void OnEnter(GameStateMachine stateMachine, IState prevState, object param1, object param2); /// <summary> /// 离开状态时回调此方法 /// </summary> /// <param name="nextState">离开此状态后的下一状态</param> void OnLeave(IState nextState, object param1, object param2); /// <summary> /// 每帧的OnUpdate方法回调 /// </summary> void OnUpdate(); }PlayerRunState:
using UnityEngine; using System.Collections; public class PlayerRuningState : IState { Player m_Player = null; private bool isRight; private static bool isFirst = true;//自己加的,因为OnLeave之后还是被一直调用,很烦 public PlayerRuningState(Player player) { m_Player = player; } #region IState 成员 public int GetStateID() { return (int)Player.PlayerState.Runing; } public void OnEnter(GameStateMachine stateMachine, IState prevState, object param1, object param2) { m_Player.anim.SetBool("isRun",true);//这里还有个报错,获取不到 Debug.Log("进入行走状态 上次的状态为 :" + prevState); } public void OnLeave(IState nextState, object param1, object param2) { m_Player.anim.SetBool("isRun", false); Debug.Log("退出行走状态 下次的状态为 :" + nextState); } public void OnUpdate() { float v = Input.GetAxis("Vertical"); float h = Input.GetAxis("Horizontal"); if (Mathf.Abs(h) > 0.1f) { m_Player.gameObject.transform.Translate(Vector3.forward * Time.deltaTime * v * 5); m_Player.gameObject.transform.eulerAngles += new Vector3(0, -h, 0); } else if (Mathf.Abs(v) > 0.1f) { m_Player.gameObject.transform.Translate(Vector3.forward * Time.deltaTime * v * 5); m_Player.gameObject.transform.eulerAngles += new Vector3(0, -h, 0); } if(Input.GetKeyDown(KeyCode.Space)) { m_Player.anim.SetTrigger("isJump"); m_Player.gameObject.GetComponent<Rigidbody>().AddForce(Vector3.up * 200); } } #endregion }GameStateMachine:
using UnityEngine; using System.Collections; ////////////////////////////////////////////////////////////////////////// /// Author: sheen /// Date: 2015-5-20 13:46:51 /// Description: 状态机 ////////////////////////////////////////////////////////////////////////// using System.Collections.Generic; public class GameStateMachine { /// <summary> /// 存储所有注册进来的状态。key是状态ID,value是状态对象 /// </summary> private Dictionary<int, IState> m_dictState; /// <summary> /// 当前运行的状态 /// </summary> private IState m_curState; public GameStateMachine() { m_curState = null; m_dictState = new Dictionary<int, IState>(); } /// <summary> /// 注册一个状态 /// </summary> /// <param name="state">要注册的状态</param> /// <returns>成功返回true,如果此状态ID已存在或状态为NULL,则返回false</returns> public bool RegistState(IState state) { if (null == state) { Debug.LogWarning("StateMachine::RegistState->state is null"); return false; } if (m_dictState.ContainsKey(state.GetStateID())) { Debug.LogWarning("StateMachine::RegistState->state had exist! state id=" + state.GetStateID()); return false; } m_dictState[state.GetStateID()] = state; return true; } /// <summary> /// 尝试获取一个状态 /// </summary> /// <param name="iStateId"></param> /// <returns></returns> public IState GetState(int iStateId) { IState ret = null; m_dictState.TryGetValue(iStateId, out ret); return ret; } /// <summary> /// 停止当前正在运行的状态, 切换到空状态 /// </summary> public void StopState(object param1, object param2) { if (null == m_curState) { return; } m_curState.OnLeave(null, param1, param2); m_curState = null; } /// <summary> /// 取消状态的注册 /// </summary> /// <param name="iStateID">要取消的状态ID</param> /// <returns>如果找不到状态或状态正在运行,则会返回false</returns> public bool CancelState(int iStateID) { if (!m_dictState.ContainsKey(iStateID)) { return false; } if (null != m_curState && m_curState.GetStateID() == iStateID) { return false; } return m_dictState.Remove(iStateID); } //public delegate void BetweenSwitchState(IState from, IState to, object param1, object param2); ///// <summary> ///// 在切换状态之间回调 ///// </summary> //public BetweenSwitchState BetweenSwitchStateCallBack { get; set; } /// <summary> /// 切换状态 /// </summary> /// <param name="iNewStateID">要切换的新状态</param> /// <returns>如果找不到新的状态,或者新旧状态一样,返回false</returns> public bool SwitchState(int iNewStateID, object param1, object param2) { //状态一样,不做转换// if (null != m_curState && m_curState.GetStateID() == iNewStateID) { return false; } //通过iNewStateID判断是否能够获取到状态 IState newState = null; m_dictState.TryGetValue(iNewStateID, out newState); if (null == newState) { return false; } //执行oldState的Leave状态 IState oldState = m_curState; if ( oldState!=null) { oldState.OnLeave(newState, param1, param2); oldState=null; } // if (BetweenSwitchStateCallBack != null) BetweenSwitchStateCallBack(oldState, newState, param1, param2); m_curState = newState; if (null != newState) { newState.OnEnter(this, oldState, param1, param2); } return true; } /// <summary> /// 获取当前状态 /// </summary> /// <returns></returns> public IState GetCurState() { return m_curState; } /// <summary> /// 获取当前状态ID /// </summary> /// <returns></returns> public int GetCurStateID() { IState state = GetCurState(); return (null == state) ? 0 : state.GetStateID(); } /// <summary> /// 判断当前是否在某个状态下 /// </summary> /// <param name="iStateID"></param> /// <returns></returns> public bool IsInState(int iStateID) { if (null == m_curState) { return false; } return m_curState.GetStateID() == iStateID; } /// <summary> /// 每帧的更新回调 /// </summary> public void OnUpdate() { if (null != m_curState) { m_curState.OnUpdate(); } } }Player:
using UnityEngine; using System.Collections; public class Player : MonoBehaviour { public Animator anim; private Rigidbody rigid; public static int isIdel = 2; GameStateMachine playerGameStateMachine = new GameStateMachine(); public enum PlayerState { Ide = 0, Runing = 1, NULL=2 } void Awake() { rigid = this.gameObject.GetComponent<Rigidbody>(); //注册所有状态// playerGameStateMachine.RegistState(new PlayerIdeState(this)); //注册待机状态// playerGameStateMachine.RegistState(new PlayerRuningState(this)); //注册行走状态// //设置默认状态 playerGameStateMachine.SwitchState((int)PlayerState.Ide, null, null); } void Update() { playerGameStateMachine.OnUpdate(); //进入行走状态 if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D)) { isIdel = 2; playerGameStateMachine.SwitchState((int)PlayerState.Runing, null, null); } else { if (isIdel == 2) { playerGameStateMachine.SwitchState((int)PlayerState.Ide, null, null); isIdel++; } } } }