这次给大家分享一个简单的有限状态机,相信你看了我这篇博客会马上理解和使用,好了废话不多说了先上一张整体的架构图:
接下来就是代码的实现:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色有限状态机抽象基类.
/// </summary>
public abstract class RoleStateAbstract{
/// <summary>
/// 当前有限状态机管理器.
/// </summary>
public RoleFSMMgr CurrRoleFSMMgr { get; private set; }
/// <summary>
/// 当前动画状态片段信息.
/// </summary>
public AnimatorStateInfo currAnimatorStateInfo { get; set; }
/// <summary>
/// 构造函数.
/// </summary>
public RoleStateAbstract(RoleFSMMgr roleFSMMgr)
{
CurrRoleFSMMgr = roleFSMMgr;
}
/// <summary>
/// 进入状态.
/// </summary>
public virtual void OnEnter() { }
/// <summary>
/// 执行状态.
/// </summary>
public virtual void OnUpdate() { }
/// <summary>
/// 离开状态.
/// </summary>
public virtual void OnExit() { }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色待机状态.
/// </summary>
public class RoleStateIdle : RoleStateAbstract {
public RoleStateIdle(RoleFSMMgr roleFSMMgr) : base(roleFSMMgr)
{
}
/// <summary>
/// 实现基类 进入状态方法.
/// </summary>
public override void OnEnter()
{
base.OnEnter();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToIdleNormal.ToString(),true);
}
/// <summary>
/// 实现基类 执行状态方法.
/// </summary>
public override void OnUpdate()
{
base.OnUpdate();
currAnimatorStateInfo = CurrRoleFSMMgr.CurrRoleCtrl._Animator.GetCurrentAnimatorStateInfo(0);
if (currAnimatorStateInfo.IsName(RoleAnimatorName.Idle_Normal.ToString()))
{
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.CurrState.ToString(), (int)RoleState.Idle);
}
}
/// <summary>
/// 实现基类 离开状态方法.
/// </summary>
public override void OnExit()
{
base.OnExit();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToIdleNormal.ToString(), false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色跑状态.
/// </summary>
public class RoleStateRun : RoleStateAbstract
{
public RoleStateRun(RoleFSMMgr roleFSMMgr) : base(roleFSMMgr)
{
}
/// <summary>
/// 实现基类 进入状态方法.
/// </summary>
public override void OnEnter()
{
base.OnEnter();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToRun.ToString(), true);
}
/// <summary>
/// 实现基类 执行状态方法.
/// </summary>
public override void OnUpdate()
{
base.OnUpdate();
currAnimatorStateInfo = CurrRoleFSMMgr.CurrRoleCtrl._Animator.GetCurrentAnimatorStateInfo(0);
if (currAnimatorStateInfo.IsName(RoleAnimatorName.Run.ToString()))
{
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.CurrState.ToString(), (int)RoleState.Run);
}
}
/// <summary>
/// 实现基类 离开状态方法.
/// </summary>
public override void OnExit()
{
base.OnExit();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToRun.ToString(), false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色攻击状态.
/// </summary>
public class RoleStateAttack : RoleStateAbstract
{
public RoleStateAttack(RoleFSMMgr roleFSMMgr) : base(roleFSMMgr)
{
}
/// <summary>
/// 实现基类 进入状态方法.
/// </summary>
public override void OnEnter()
{
base.OnEnter();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.ToPhyAttack.ToString(), 1);
}
/// <summary>
/// 实现基类 执行状态方法.
/// </summary>
public override void OnUpdate()
{
base.OnUpdate();
currAnimatorStateInfo = CurrRoleFSMMgr.CurrRoleCtrl._Animator.GetCurrentAnimatorStateInfo(0);
if (currAnimatorStateInfo.IsName(RoleAnimatorName.PhyAttack1.ToString()))
{
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.CurrState.ToString(), (int)RoleState.Attack);
//如果动画已经播放过一次 就切换到待机.
if (currAnimatorStateInfo.normalizedTime > 1)
{
CurrRoleFSMMgr.CurrRoleCtrl.ToIdle();
}
}
}
/// <summary>
/// 实现基类 离开状态方法.
/// </summary>
public override void OnExit()
{
base.OnExit();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.ToPhyAttack.ToString(), 0);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色死亡状态.
/// </summary>
public class RoleStateDie : RoleStateAbstract
{
public RoleStateDie(RoleFSMMgr roleFSMMgr) : base(roleFSMMgr)
{
}
/// <summary>
/// 实现基类 进入状态方法.
/// </summary>
public override void OnEnter()
{
base.OnEnter();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToDie.ToString(), true);
}
/// <summary>
/// 实现基类 执行状态方法.
/// </summary>
public override void OnUpdate()
{
base.OnUpdate();
currAnimatorStateInfo = CurrRoleFSMMgr.CurrRoleCtrl._Animator.GetCurrentAnimatorStateInfo(0);
if (currAnimatorStateInfo.IsName(RoleAnimatorName.Die.ToString()))
{
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetInteger(ToAnimatorCondition.CurrState.ToString(), (int)RoleState.Die);
}
}
/// <summary>
/// 实现基类 离开状态方法.
/// </summary>
public override void OnExit()
{
base.OnExit();
CurrRoleFSMMgr.CurrRoleCtrl._Animator.SetBool(ToAnimatorCondition.ToDie.ToString(), false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色状态机管理器.
/// </summary>
public class RoleFSMMgr{
/// <summary>
/// 当前角色控制器.
/// </summary>
public RoleCtrl CurrRoleCtrl { get; private set; }
/// <summary>
/// 当前角色状态枚举.
/// </summary>
public RoleState currRoleStateEmun { get; private set; }
/// <summary>
/// 当前角色状态.
/// </summary>
private RoleStateAbstract currRoleState = null;
private Dictionary<RoleState, RoleStateAbstract> roleStateDic;
/// <summary>
/// 构造函数.
/// </summary>
public RoleFSMMgr(RoleCtrl currRoleCtrl)
{
CurrRoleCtrl = currRoleCtrl;
roleStateDic = new Dictionary<RoleState, RoleStateAbstract>();
roleStateDic[RoleState.Idle] = new RoleStateIdle(this);
roleStateDic[RoleState.Run] = new RoleStateRun(this);
roleStateDic[RoleState.Hurt] = new RoleStateHurt(this);
roleStateDic[RoleState.Attack] = new RoleStateAttack(this);
roleStateDic[RoleState.Die] = new RoleStateDie(this);
if (roleStateDic.ContainsKey(currRoleStateEmun))
{
currRoleState = roleStateDic[currRoleStateEmun];
}
}
/// <summary>
/// 每帧执行.
/// </summary>
public void OnUpdate()
{
if (currRoleState != null)
{
currRoleState.OnUpdate();
}
}
/// <summary>
/// 切换状态.
/// </summary>
/// <param name="newState"></param>
public void ChangeState(RoleState newState)
{
if (currRoleStateEmun == newState) return;//如果相等直接返回 不需要重复执行同一个状态.
//调用以前状态的离开方法.
if (currRoleState != null)
{
currRoleState.OnExit();
}
//更改当前状态枚举.
currRoleStateEmun = newState;
//更改当前状态.
currRoleState = roleStateDic[newState];
//新状态执行进入方法.
currRoleState.OnEnter();
}
}
#region 角色状态
/// <summary>
/// 角色状态.
/// </summary>
public enum RoleState
{
/// <summary>
/// 未设置.
/// </summary>
None=0,
/// <summary>
/// 待机.
/// </summary>
Idle=1,
/// <summary>
/// 跑.
/// </summary>
Run=2,
/// <summary>
/// 攻击.
/// </summary>
Attack=3,
/// <summary>
/// 受伤.
/// </summary>
Hurt=4,
/// <summary>
/// 死亡.
/// </summary>
Die=5
}
#endregion
#region 角色动画名字.
/// <summary>
/// 角色动画名字.
/// </summary>
public enum RoleAnimatorName
{
Idle_Normal,
Idle_Fight,
Run,
Die,
Hurt,
PhyAttack1,
PhyAttack2,
PhyAttack3
}
#endregion
#region 角色动画条件.
/// <summary>
/// 角色动画条件.
/// </summary>
public enum ToAnimatorCondition
{
ToIdleNormal,
ToIdleFight,
ToRun,
ToDie,
ToHurt,
ToPhyAttack,
CurrState
}
#endregion
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 角色控制器.
/// </summary>
public class RoleCtrl : MonoBehaviour {
/// <summary>
/// 角色动画组件.
/// </summary>
public Animator _Animator;
/// <summary>
/// 当前角色有限状态机管理器.
/// </summary>
public RoleFSMMgr currRoleFSMMgr = null;
private void Start()
{
currRoleFSMMgr = new RoleFSMMgr(this);
}
private void Update()
{
if (currRoleFSMMgr != null)
{
currRoleFSMMgr.OnUpdate();//实时更新状态.
}
if (Input.GetKeyDown(KeyCode.Alpha0))
{
ToIdle();
}else if (Input.GetKeyDown(KeyCode.Alpha1))
{
ToRun();
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
ToAttack();
}
else if (Input.GetKeyDown(KeyCode.Alpha3))
{
ToHurt();
}
else if (Input.GetKeyDown(KeyCode.Alpha4))
{
ToDie();
}
}
#region 角色操作方法.
/// <summary>
/// 切换到跑.
/// </summary>
public void ToRun()
{
currRoleFSMMgr.ChangeState(RoleState.Run);
}
/// <summary>
/// 切换到攻击.
/// </summary>
public void ToAttack()
{
currRoleFSMMgr.ChangeState(RoleState.Attack);
}
/// <summary>
/// 切换到受伤.
/// </summary>
public void ToHurt()
{
currRoleFSMMgr.ChangeState(RoleState.Hurt);
}
/// <summary>
/// 切换到待机.
/// </summary>
public void ToIdle()
{
currRoleFSMMgr.ChangeState(RoleState.Idle);
}
/// <summary>
/// 切换到死亡.
/// </summary>
public void ToDie()
{
currRoleFSMMgr.ChangeState(RoleState.Die);
}
#endregion
}
项目工程源码地址:链接: https://pan.baidu.com/s/1jWag6DFVpSfw36rBet1xSQ 提取码: cxvw