using UnityEngine;
using System.Collections;
public class PlayerCtr : MonoBehaviour {
[SerializeField]
private EasyJoystick joyStick;
private StateMachine m_StateMachine;
public Animation ani;
// Use this for initialization
void Start () {
//初始状态机
m_StateMachine = new StateMachine(new IdleState(0, this));
InitState();
}
void InitState()
{
m_StateMachine.RegisterState(new RunState(1,this));
m_StateMachine.RegisterState(new AttackState(2,this));
m_StateMachine.RegisterState(new DefendState(3,this));
m_StateMachine.RegisterState(new JumpState(4,this));
m_StateMachine.RegisterState(new DieState(5,this));
}
// Update is called once per frame
void Update () {
float x = joyStick.JoystickTouch.x;
float z = joyStick.JoystickTouch.y;
if (x != 0 || z != 0)
{
transform.LookAt(new Vector3(x,0,z) + transform.position);
m_StateMachine.TranslateToState(2);
}
}
void LateUpdate()
{
m_StateMachine.FSMUpdate();
}
void OnDrag(Vector2 delta)
{
Debug.Log(delta);
transform.Rotate(-Vector3.up*delta.normalized.x*10f);
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 状态机
/// </summary>
public class StateMachine{
/// <summary>
/// 状态缓存
/// </summary>
public Dictionary<int, StateBase> m_StateCache;
/// <summary>
/// 当前状态
/// </summary>
public StateBase m_CurrentState;
/// <summary>
/// 当前状态的前一个状态
/// </summary>
public StateBase m_PreviousState;
#region StateMachine Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="beginState">开始状态</param>
public StateMachine(StateBase beginState)
{
m_PreviousState = null;
m_CurrentState = beginState;
m_StateCache = new Dictionary<int, StateBase>();
//注册状态
RegisterState(beginState);
m_CurrentState.OnEnter();
}
#endregion
#region FSMUpdate 状态机监测状态
/// <summary>
/// 状态机监测状态变化
/// </summary>
public void FSMUpdate()
{
if (m_CurrentState != null)
m_CurrentState.OnStay();
}
#endregion
#region TranslateToState 状态切换
/// <summary>
/// 状态切换
/// </summary>
/// <param name="id">目标状态的id号</param>
/// <param name="args">可变参数</param>
public void TranslateToState(int id,params object[] args)
{
int key_id = id;
if (!m_StateCache.ContainsKey(key_id))
{
Debug.LogError("The key is not Exist");
return;
}
//状态转换检测
if(m_CurrentState.GetType().Name!= m_StateCache [key_id].GetType().Name){
if (FromToCtr.fo [m_StateCache [key_id].GetType().Name].Contains (m_CurrentState.GetType().Name)==false) {
Debug.LogError("Can not to transtrate");
return;
}
}
//当前状态退出
m_CurrentState.OnExit();
//保存当前状态为下一个新状态的前一个状态
m_PreviousState = m_CurrentState;
//当前状态更新到下一个新状态
m_CurrentState = m_StateCache[key_id];
//新的状态开始进入
m_CurrentState.OnEnter(args);
}
#endregion
#region RegisterState 注册一个新的状态到缓存中
/// <summary>
/// 注册一个新的状态到缓存中
/// </summary>
/// <param name="aState">新状态</param>
public void RegisterState(StateBase aState)
{
int id = aState.ID;
//状态是否缓存了
if (m_StateCache.ContainsKey(id))
{
Debug.LogError("The State has been added the Cache");
return;
}
//缓存aState状态
m_StateCache.Add(id,aState);
//设置aState状态的状态机对象
aState.machine = this;
}
#endregion
}
using UnityEngine;
using System.Collections;/// <summary>
/// 状态基类
/// </summary>
public abstract class StateBase {
/// <summary>
/// 每个状态对应不同的ID号
/// </summary>
public int ID { get; private set; }
/// <summary>
/// 状态机
/// </summary>
public StateMachine machine;
/// <summary>
/// Construtor
/// </summary>
/// <param name="id">状态的id号(id号有对应的枚举)</param>
public StateBase(int id)
{
ID = id;
}
/// <summary>
/// 状态进入时调用一次
/// </summary>
public virtual void OnEnter(params object[] args)
{
}
/// <summary>
/// 状态退出时调用一次
/// </summary>
public virtual void OnExit(params object[] args)
{ }
/// <summary>
/// 状态进入后,每帧调用一次
/// </summary>
public virtual void OnStay(params object[] args)
{ }
}
using UnityEngine;
using System.Collections;
/// <summary>
/// 状态模板
/// </summary>
public class StateTemplate<T> :StateBase {
/// <summary>
/// 状态的拥有者
/// </summary>
public T m_owner;
/// <summary>
/// Constructor
/// </summary>
/// <param name="id">状态的id号</param>
/// <param name="owner">状态的拥有者</param>
public StateTemplate(int id,T owner):base(id)
{
m_owner = owner;
}
}
using UnityEngine;
using System.Collections;
public class AttackState : StateTemplate<PlayerCtr> {
public AttackState(int id,PlayerCtr owner):base(id,owner)
{
}
public override void OnEnter (params object[] args)
{
base.OnEnter (args);
Debug.Log ("attack Enter");
m_owner.ani.Play ("Attack");
}
public override void OnStay (params object[] args)
{
base.OnStay (args);
}
public override void OnExit (params object[] args)
{
base.OnExit (args);
Debug.Log ("attack Exit");
}
}