格斗游戏角色控制之U3D状态机的编写

先简单介绍下状态机机的大概工作流程

转载自http://blog.csdn.net/code_sheen/

格斗游戏角色控制之U3D状态机的编写_第1张图片

一般格斗游戏都是由许多的角色肯定不可能一个脚本控制所有的角色所以每个角色肯定会有相应的角色控制脚本,每个角色都会有很多

转载自http://blog.csdn.net/code_sheen/

个状态那么自己编写个状态机肯定是很有必要的,那么今天我就给大家分享个状态机玩玩,希望大家相互学习

转载自http://blog.csdn.net/code_sheen/

状态机一般分为两部分 1.状态总管理 2.状态机接口

转载自http://blog.csdn.net/code_sheen/

再给大家画个状态机的流程图 

格斗游戏角色控制之U3D状态机的编写_第2张图片


每个状态之间是互不影响的 都是靠状态机的管理所有的状态  进入下一个状态 退出当前状态

转载自http://blog.csdn.net/code_sheen/

好吧上代码

转载自http://blog.csdn.net/code_sheen/

状态机接口类

IState.cs

//
/// Author: sheen
/// Date: 2015-5-20 13:47:19
/// Description: 状态接口
//

public interface IState
{
    /// 
    /// 获取状态ID
    /// 
    /// 
    int GetStateID();

    /// 
    /// 进入状态回调此方法
    /// 
    /// 控制此状态的状态机
    /// 进入此状态的前状态
    void OnEnter(GameStateMachine stateMachine, IState prevState, object param1, object param2);

    /// 
    /// 离开状态时回调此方法
    /// 
    /// 离开此状态后的下一状态
    void OnLeave(IState nextState, object param1, object param2);

    /// 
    /// 每帧的OnUpdate方法回调
    /// 
    void OnUpdate();

    /// 
    /// 每帧的FixedUpdate回调
    /// 
    void OnFixedUpdate();

    /// 
    /// 每帧的LateUpdate回调
    /// 
    void OnLateUpdate();
}

转载自http://blog.csdn.net/code_sheen/

状态管理脚本
GameStateMachine.cs

转载自http://blog.csdn.net/code_sheen/

using UnityEngine;
using System.Collections;

//
/// Author: sheen
/// Date: 2015-5-20 13:46:51
/// Description: 状态机
//
using System.Collections.Generic;
using UnityEngine;

public class GameStateMachine 
{
    /// 
    /// 存储所有注册进来的状态。key是状态ID,value是状态对象
    /// 
    private Dictionary m_dictState;
    /// 
    /// 当前运行的状态
    /// 
    private IState m_curState;

    public GameStateMachine()
    {
        m_curState = null;
        m_dictState = new Dictionary();
    }

    /// 
    /// 注册一个状态
    /// 
    /// 要注册的状态
    /// 成功返回true,如果此状态ID已存在或状态为NULL,则返回false
    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;
    }

    /// 
    /// 尝试获取一个状态
    /// 
    /// 
    /// 
    public IState GetState(int iStateId)
    {
        IState ret = null;
        m_dictState.TryGetValue(iStateId, out ret);
        return ret;
    }

    /// 
    /// 停止当前正在运行的状态, 切换到空状态
    /// 
    public void StopState(object param1, object param2)
    {
        if (null == m_curState)
        {
            return;
        }

        m_curState.OnLeave(null, param1, param2);

        m_curState = null;
    }

    /// 
    /// 取消状态的注册
    /// 
    /// 要取消的状态ID
    /// 如果找不到状态或状态正在运行,则会返回false
    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);

    /// 
    /// 在切换状态之间回调
    /// 
    public BetweenSwitchState BetweenSwitchStateCallBack { get; set; }

    /// 
    /// 切换状态
    /// 
    /// 要切换的新状态
    /// 如果找不到新的状态,或者新旧状态一样,返回false
    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;
    }

    /// 
    /// 获取当前状态
    /// 
    /// 
    public IState GetCurState()
    {
        return m_curState;
    }

    /// 
    /// 获取当前状态ID
    /// 
    /// 
    public int GetCurStateID()
    {
        IState state = GetCurState();
        return (null == state) ? 0 : state.GetStateID();
    }

    /// 
    /// 判断当前是否在某个状态下
    /// 
    /// 
    /// 
    public bool IsInState(int iStateID)
    {
        if (null == m_curState)
        {
            return false;
        }

        return m_curState.GetStateID() == iStateID;
    }

    /// 
    /// 每帧的更新回调
    /// 
    public void OnUpdate()
    {
        if (null != m_curState)
        {
            m_curState.OnUpdate();
        }
    }

    /// 
    /// 每帧的更新回调
    /// 
    public void OnFixedUpdate()
    {
        if (null != m_curState)
        {
            m_curState.OnFixedUpdate();
        }
    }

    /// 
    /// 每帧的更新回调
    /// 
    public void OnLateUpdate()
    {
        if (null != m_curState)
        {
            m_curState.OnLateUpdate();
        }
    }
}

转载自 http://blog.csdn.net/code_sheen/

接下来写个写个使用示例

转载自http://blog.csdn.net/code_sheen/

先写角色控制脚本

player.cs

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

    GameStateMachine playerGameStateMachine = new GameStateMachine();
    public enum PlayerState
    {
        /// 
        /// 待机
        /// 
        Ide = 0,

        /// 
        /// 行走
        /// 
        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());
    }
}

转载自 http://blog.csdn.net/code_sheen/

两个状态  待机  和 行走

转载自http://blog.csdn.net/code_sheen/

待机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
}

转载自 http://blog.csdn.net/code_sheen/

行走 PlayerRuningState.cs

转载自http://blog.csdn.net/code_sheen/

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://blog.csdn.net/code_sheen/

最后 看看效果 

格斗游戏角色控制之U3D状态机的编写_第3张图片



下面是工程的地址:链接: http://pan.baidu.com/s/1hqzUlJu 密码: gwsc














你可能感兴趣的:(unity3D)