您需要 登录 才可以下载或查看,没有账号?注册
x
本帖最后由 醉酒風 于 2019-5-13 22:17 编辑
转自小新的干货。很不错的~!
先简单介绍下状态机机的大概工作流程
一般格斗游戏都是有许多的角色,
肯定不可能一个脚本控制所有的角色。
所以每个角色肯定会有相应的角色控制脚本,
每个角色都会有很多个状态,那么自己编写个状态机肯定是很有必要的。
那么今天我就给大家分享个状态机玩玩,希望大家相互学习状态机
一般分为两部分 1.状态总管理 2.状态机接口
再给大家画个状态机的流程图
每个状态之间是互不影响的 都是靠状态机的管理所有的状态
进入下一个状态 退出当前状态
好吧上代码
状态机接口类
IState.cs
- //////////////////////////////////////////////////////////////////////////
- /// Author: sheen
- /// Date: 2015-5-20 13:47:19
- /// Description: 状态接口
- //////////////////////////////////////////////////////////////////////////
- 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();
- /// <summary>
- /// 每帧的FixedUpdate回调
- /// </summary>
- void OnFixedUpdate();
- /// <summary>
- /// 每帧的LateUpdate回调
- /// </summary>
- void OnLateUpdate();
- }
点击此处复制文本
状态管理脚本
GameStateMachine.cs
- using UnityEngine;
- using System.Collections;
- //////////////////////////////////////////////////////////////////////////
- /// Author: sheen
- /// Date: 2015-5-20 13:46:51
- /// Description: 状态机
- //////////////////////////////////////////////////////////////////////////
- using System.Collections.Generic;
- using UnityEngine;
- 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;
- }
- IState newState = null;
- m_dictState.TryGetValue(iNewStateID, out newState);
- if (null == newState)
- {
- return false;
- }
- IState oldState = m_curState;
- if (null != oldState)
- {
- oldState.OnLeave(newState, param1, param2);
- }
- 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();
- }
- }
- /// <summary>
- /// 每帧的更新回调
- /// </summary>
- public void OnFixedUpdate()
- {
- if (null != m_curState)
- {
- m_curState.OnFixedUpdate();
- }
- }
- /// <summary>
- /// 每帧的更新回调
- /// </summary>
- public void OnLateUpdate()
- {
- if (null != m_curState)
- {
- m_curState.OnLateUpdate();
- }
- }
- }
点击此处复制文本
接下来写个写个使用示例
先写角色控制脚本
player.cs
- using UnityEngine;
- using System.Collections;
-
- public class Player : MonoBehaviour {
-
- GameStateMachine playerGameStateMachine = new GameStateMachine();
- public enum PlayerState
- {
- /// <summary>
- /// 待机
- /// </summary>
- Ide = 0,
-
- /// <summary>
- /// 行走
- /// </summary>
- Runing = 1,
- }
-
- void Awake()
- {
- //注册所有状态//
- playerGameStateMachine.RegistState(new PlayerIdeState(this)); //注册待机状态//
- playerGameStateMachine.RegistState(new PlayerRuningState(this)); //注册行走状态//
-
-
- playerGameStateMachine.SwitchState((int)PlayerState.Ide, null, null);
- }
-
- void Update()
- {
- if (playerGameStateMachine.GetCurState() != null)
- {
- currentstate = (PlayerState)playerGameStateMachine.GetCurStateID();
- }
- playerGameStateMachine.OnUpdate();
- }
-
- void FixedUpdate()
- {
- playerGameStateMachine.OnFixedUpdate();
- }
-
- void LateUpdate()
- {
- playerGameStateMachine.OnLateUpdate();
- }
-
- private PlayerState currentstate = PlayerState.Ide;
-
- void OnGUI()
- {
- if(GUI.Button(new Rect(0,0,300,50),"切换成待机状态"))
- {
- playerGameStateMachine.SwitchState((int)PlayerState.Ide,null,null);
- }
- if (GUI.Button(new Rect(360,0, 300, 50), "切换成行走状态"))
- {
- playerGameStateMachine.SwitchState((int)PlayerState.Runing, null, null);
- }
- GUI.Label(new Rect(60, 60, 300, 200), "currntState:"+currentstate.ToString());
- }
- }
点击此处复制文本
两个状态 待机 和 行走
待机PlayerIdeState.cs
- using UnityEngine;
- using System.Collections;
-
- public class PlayerIdeState : IState
- {
- Player m_Player = null;
- public PlayerIdeState (Player player)
- {
- m_Player = player;
- }
- #region IState 成员
-
- public int GetStateID()
- {
- return (int)Player.PlayerState.Ide;
- }
-
- public void OnEnter(GameStateMachine stateMachine, IState prevState, object param1, object param2)
- {
- isUp = false;
- m_Player.transform.position = UnityEngine.Vector3.zero;
- Debug.Log("进入待机状态 上次的状态为 :" + prevState);
- }
-
- public void OnLeave(IState nextState, object param1, object param2)
- {
- Debug.Log("退出待机状态 下次的状态为 :" + nextState);
- }
-
- bool isUp = true;
- public void OnUpdate()
- {
-
- if (m_Player.transform.position.y >= 0.5)
- {
- isUp = false;
- }
- if (m_Player.transform.position.y <= 0)
- {
- isUp = true;
- }
- if (isUp)
- {
- m_Player.transform.position += new UnityEngine.Vector3(0.0f, 0.5f, 0.0f) * Time.deltaTime;
- }
- else
- {
- m_Player.transform.position -= new UnityEngine.Vector3(0.0f, 0.5f, 0.0f) * Time.deltaTime;
- }
-
- }
-
- public void OnFixedUpdate()
- {
- }
-
- public void OnLateUpdate()
- {
- }
-
- #endregion
- }
点击此处复制文本
行走 PlayerRuningState.cs
- using UnityEngine;
- using System.Collections;
-
- public class PlayerRuningState : IState
- {
- Player m_Player = null;
- private bool isRight;
- 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)
- {
- isRight = true;
- m_Player.transform.position = UnityEngine.Vector3.zero;
- Debug.Log("进入行走状态 上次的状态为 :" + prevState);
- }
-
- public void OnLeave(IState nextState, object param1, object param2)
- {
- Debug.Log("退出行走状态 下次的状态为 :" + nextState);
- }
-
- public void OnUpdate()
- {
- if (m_Player.transform.position.x >= 0.5)
- {
- isRight = false;
- }
- if (m_Player.transform.position.x <= 0)
- {
- isRight = true;
- }
- if (isRight)
- {
- m_Player.transform.position += new UnityEngine.Vector3(0.5f, 0.0f, 0.0f) * Time.deltaTime;
- }
- else
- {
- m_Player.transform.position -= new UnityEngine.Vector3(0.5f, 0, 0.0f) * Time.deltaTime;
- }
- }
-
- public void OnFixedUpdate()
- {
- }
-
- public void OnLateUpdate()
- {
- }
-
- #endregion
- }
点击此处复制文本
最后看看效果
小新的个人博客 http://www.liyingxin.com
工程下载地址:回复可见~
尊敬的 游客,如果您要查看本帖关注 或 回复可见内容请 关注或 回复后刷新页面查看!
|