您的位置:首页 > 移动开发 > Unity3D

unity3d状态机基础学习(二)

2017-02-03 14:39 232 查看
之前介绍了状态及状态机的概念,并且有个简单的跳转。

下面深入一点,写一个人物的普通状态、寻路状态导致的动作变化(站立状态到移动状态到骑马状态)

1、State类保持不变

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");
return;
}
if (curState != null && !curState.nextStates.Contains(_newState))
{
Debug.LogError("can't change to the state that curState don't contains");
return;
}

//触发退出状态调用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);
}

public void SetInitState(State _curState)
{
curState = _curState;
lastState = new State("init");
curState.Enter(lastState, _curState);
}

public string GetCurStateName()
{
if (curState != null)
{
return curState.name;
}
return string.Empty;
}

///
/// 重启状态机
///
public void Restart()
{

}
}


3、添加了一个继承MonoBehaviour的基类FSMBase,要用到状态变化就继承这个类

using UnityEngine;
using System.Collections;

public class FSMBase : MonoBehaviour {

protected Machine stateMachine;
void Start () {
stateMachine = new Machine();
InitStateMachine();
}

void Update()
{
if (stateMachine != null)
stateMachine.Update();
}

public virtual void Reset()
{
if (stateMachine != null)
stateMachine.Restart();
}

protected virtual void InitStateMachine() { }
}


4、上篇中的TestMachine改为AnimMachine,并且添加了骑马状态的情况

using UnityEngine;
using System.Collections;

public class AnimMachine : FSMBase {

protected State moveState = null;
protected State idleState = null;
protected State attackState = null;
protected State rideState = null;

protected override void InitStateMachine()
{
base.InitStateMachine();
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;

rideState = new State("ride");
rideState.onEnter = EnterRide;
rideState.onExit = ExitRide;
rideState.onAction = ExcuteRide;

idleState.nextStates.Add(moveState);
idleState.nextStates.Add(attackState);
idleState.nextStates.Add(rideState);

moveState.nextStates.Add(idleState);
moveState.nextStates.Add(attackState);
moveState.nextStates.Add(rideState);

attackState.nextStates.Add(idleState);
attackState.nextStates.Add(moveState);

rideState.nextStates.Add(idleState);

stateMachine.SetInitState(idleState);
}

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 EnterRide(State _from, State _to)
{
Debug.Log("EnterRide _from:" + _from.name);
}
void ExitRide(State _from, State _to)
{
Debug.Log("ExitRide _to:" + _to.name);
}
void ExcuteRide(State _curState)
{

}

public void Idle()
{
if (stateMachine != null)
stateMachine.ChangeState(idleState);
}

public void Move()
{
if (stateMachine != null)
stateMachine.ChangeState(moveState);
}

public void Ride()
{
if (stateMachine != null)
stateMachine.ChangeState(rideState);
}
}


5、主玩家类,MainPlayer

using UnityEngine;
using System.Collections;

public class MainPlayer : FSMBase {

protected State normalState = null;
protected State taskPathState = null;//任务寻路

private AnimMachine animMachaine = null;

void Awake()
{
if (animMachaine == null)
{
animMachaine = gameObject.GetComponent();
}
if (animMachaine == null)
{
animMachaine = gameObject.AddComponent();
}
}

protected override void InitStateMachine()
{
base.InitStateMachine();
normalState = new State("normal");
normalState.onEnter = EnterNormalState;
normalState.onExit = ExitNormalState;
normalState.onAction = ExcuteNormalState;

taskPathState = new State("taskPathState");
taskPathState.onEnter = EnterTaskPathState;
taskPathState.onExit = ExitTaskPathState;
taskPathState.onAction = ExcuteTaskPathState;

normalState.nextStates.Add(taskPathState);

taskPathState.nextStates.Add(normalState);

stateMachine.SetInitState(normalState);
}

void EnterNormalState(State _from, State _to)
{
Debug.Log("EnterNormalState _from:" + _from.name);
animMachaine.Idle();
}
void ExitNormalState(State _from, State _to)
{
Debug.Log("ExitNormalState _to:" + _to.name)
4000
;
}
void ExcuteNormalState(State _curState)
{

}

protected float enterTaskPathTime = 0f;
protected bool isRiding = false;
void EnterTaskPathState(State _from, State _to)
{
Debug.Log("EnterTaskPathState _from:" + _from.name);
animMachaine.Move();
enterTaskPathTime = Time.time;
}
void ExitTaskPathState(State _from, State _to)
{
Debug.Log("ExitTaskPathState _to:" + _to.name);
isRiding = false;
}
void ExcuteTaskPathState(State _curState)
{
if (Time.time - enterTaskPathTime > 5f && !isRiding)
{
animMachaine.Ride();
isRiding = true;
}
}

void OnGUI()
{
if (GUILayout.Button("normal"))
{
if (stateMachine != null)
stateMachine.ChangeState(normalState);
}
if (GUILayout.Button("taskPath"))
{
if (stateMachine != null)
stateMachine.ChangeState(taskPathState);
}

GUILayout.Label(stateMachine != null ? stateMachine.GetCurStateName() : "");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity3d 状态机