unity3d状态机基础学习(二)

之前介绍了状态及状态机的概念,并且有个简单的跳转。

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

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);
    }
    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() : "");
    }
}

    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值