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

毕业设计之角色状态机

2018-03-26 14:34 316 查看
      这两天一直没做多少毕设的东西,只是简单的实现了下fsm状态机,之前只是了解并没有彻底接触过,学习了一下发现并没有想象中那么复杂,于是根据一篇教程自己改动了下。状态机果然好用,把逻辑简化了很多,虽然代码量多了很多。原贴地址:https://blog.csdn.net/code_sheen/article/details/45869505


IState:

     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();

}
PlayerRunState:
using UnityEngine;
using System.Collections;

public class PlayerRuningState : IState
{
Player m_Player = null;
private bool isRight;
private static bool isFirst = true;//自己加的,因为OnLeave之后还是被一直调用,很烦
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)
{
m_Player.anim.SetBool("isRun",true);//这里还有个报错,获取不到
Debug.Log("进入行走状态 上次的状态为 :" + prevState);
}

public void OnLeave(IState nextState, object param1, object param2)
{

m_Player.anim.SetBool("isRun", false);
Debug.Log("退出行走状态 下次的状态为 :" + nextState);
}

public void OnUpdate()
{
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");

if (Mathf.Abs(h) > 0.1f)
{
m_Player.gameObject.transform.Translate(Vector3.forward * Time.deltaTime * v * 5);
m_Player.gameObject.transform.eulerAngles += new Vector3(0, -h, 0);

}
else if (Mathf.Abs(v) > 0.1f)
{
m_Player.gameObject.transform.Translate(Vector3.forward * Time.deltaTime * v * 5);
m_Player.gameObject.transform.eulerAngles += new Vector3(0, -h, 0);

}
if(Input.GetKeyDown(KeyCode.Space))
{
m_Player.anim.SetTrigger("isJump");
m_Player.gameObject.GetComponent<Rigidbody>().AddForce(Vector3.up * 200);
}
}

#endregion
}
GameStateMachine:
using UnityEngine;
using System.Collections;

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

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;
}
//通过iNewStateID判断是否能够获取到状态
IState newState = null;
m_dictState.TryGetValue(iNewStateID, out newState);
if (null == newState)
{
return false;
}
//执行oldState的Leave状态
IState oldState = m_curState;
if ( oldState!=null)
{

oldState.OnLeave(newState, param1, param2);
oldState=null;
}
// if (BetweenSwitchStateCallBack != null) BetweenSwitchStateCallBack(oldState, newState, param1, param2);
m_curState = newState;
if (null != newState)
{
newState.OnEnter(this, oldState, param1, param2);
}

return true;
}

/// <summary>
/// 获取当前状态
/// </summary>
/// <return
4000
s></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();
}
}
}
Player:
using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
public Animator anim;
private Rigidbody rigid;
public static int isIdel = 2;
GameStateMachine playerGameStateMachine = new GameStateMachine();
public enum PlayerState
{
Ide = 0,
Runing = 1,
NULL=2
}

void Awake()
{
rigid = this.gameObject.GetComponent<Rigidbody>();
//注册所有状态//
playerGameStateMachine.RegistState(new PlayerIdeState(this)); //注册待机状态//
playerGameStateMachine.RegistState(new PlayerRuningState(this)); //注册行走状态//
//设置默认状态
playerGameStateMachine.SwitchState((int)PlayerState.Ide, null, null);
}

void Update()
{
playerGameStateMachine.OnUpdate();

//进入行走状态
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D))
{
isIdel = 2;
playerGameStateMachine.SwitchState((int)PlayerState.Runing, null, null);
}
else
{
if (isIdel == 2)
{

playerGameStateMachine.SwitchState((int)PlayerState.Ide, null, null);
isIdel++;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息