网上也有很多关于状态机的教程,我不觉得我写的比别人好。但是自己写的总是便于自己理解
这篇文章相当于自己的笔记了。。理解此文前必须懂委托
1、首先理解状态,比如人物的待机、移动、攻击。。分别是三种状态;那么我们定义一个状态的基类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class State
{
///
/// 状态名
///
public string name = "";
///
/// 构造
///
public State(string _name)
{
name = _name;
}
public State()
{
}
public delegate void TransitionEventHandler(State _from, State _to);
public delegate void OnActionHandler(State _curState);
///
/// 进入时的事件
///
public TransitionEventHandler onEnter;//System.Action
///
/// 退出时的事件
///
public TransitionEventHandler onExit;
///
/// 在状态机Update()时候调用的更新事件
///
public OnActionHandler onAction;
public virtual void Enter(State _from, State _to)
{
if (onEnter != null)
onEnter(_from, _to);
}
public virtual void Excute(State _curState)
{
if (onAction != null)
onAction(_curState);
}
public virtual void Exit(State _from, State _to)
{
if (onExit != null)
onExit(_from, _to);
}
}
2、再来理解下状态机,就是一个操作状态的机器,那么我们定义一个Machine类
using UnityEngine;
using System.Collections;
public class Machine
{
private State curState = null;
private State lastState = null;
/*Update*/
public void Update ()
{
if (curState != null)
curState.Excute(curState);
}
/*状态改变*/
public void ChangeState (State _newState)
{
if (_newState == null)
{
Debug.LogError ("can't find this state");
}
if (curState != null && _newState.name == curState.name)
Debug.LogError("can't change to the same state");
//触发退出状态调用Exit方法
curState.Exit(curState, _newState);
//保存上一个状态
lastState = curState;
//设置新状态为当前状态
curState = _newState;
//m_pCurrentState.Target = m_pOwner;
//进入当前状态调用Enter方法
curState.Enter(lastState, curState);
}
public Machine()
{
curState = null;
lastState = null;
}
public Machine(State _curState)
{
curState = _curState;
lastState = new State("init");
curState.Enter(lastState, _curState);
}
}
3、接着我们可以实例化几个状态,然后实例化一个状态机来操作这几个状态
using UnityEngine;
using System.Collections;
public class TestMachine : MonoBehaviour {
protected State moveState = null;
protected State idleState = null;
protected State attackState = null;
Machine curMachine = null;
void Start () {
idleState = new State("idle");
idleState.onEnter = EnterIdle;
idleState.onExit = ExitIdle;
idleState.onAction = ExcuteIdle;
moveState = new State("move");
moveState.onEnter = EnterMove;
moveState.onExit = ExitMove;
moveState.onAction = ExcuteMove;
attackState = new State("attack");
attackState.onEnter = EnterAttack;
attackState.onExit = ExitAttack;
attackState.onAction = ExcuteAttack;
curMachine = new Machine(idleState);
}
void Update () {
if (curMachine != null)
curMachine.Update();
}
void EnterIdle(State _from, State _to)
{
Debug.Log("EnterIdle _from:" + _from.name);
}
void ExitIdle(State _from, State _to)
{
Debug.Log("ExitIdle _to:" + _to.name);
}
void ExcuteIdle(State _curState)
{
}
void EnterMove(State _from, State _to)
{
Debug.Log("EnterMove _from:" + _from.name);
}
void ExitMove(State _from, State _to)
{
Debug.Log("ExitMove _to:" + _to.name);
}
void ExcuteMove(State _curState)
{
}
void EnterAttack(State _from, State _to)
{
Debug.Log("EnterAttack _from:" + _from.name);
}
void ExitAttack(State _from, State _to)
{
Debug.Log("ExitAttack _to:" + _to.name);
}
void ExcuteAttack(State _curState)
{
}
void OnGUI()
{
if (GUILayout.Button("idle"))
{
if (curMachine != null)
curMachine.ChangeState(idleState);
}
if (GUILayout.Button("move"))
{
if (curMachine != null)
curMachine.ChangeState(moveState);
}
if (GUILayout.Button("attack"))
{
if (curMachine != null)
curMachine.ChangeState(attackState);
}
}
}
4、接着可以多加一个骑马的状态(ride),那么此时我们需要考虑是否可以从攻击状态转换到骑马状态?骑马状态是否可以切换到攻击状态?
只需要加一个能跳转的状态List,然后在ChangeState方法里面添加判断就可以了。代码我就不贴了