20250523-简易的状态机代码模板及分析
前情提要,以下是个人对状态机的部分理解:
(1)状态机示例主要包括Player、PlayerStateMachine、PlayerState三部分;
(2)Player既作为小数据库(有点像单例模式的对象池),存储Player相关属性、创建全局唯一的状态对象和状态机对象;又通过继承MonoBehavior类,执行整个生命周期(Awake、Start、Update等),在各个生命周期函数中调用状态机对象;Player对象本身代表Unity悬挂脚本的组件;
(3)PlayerStateMachine为状态机对象,主要维护一个属性,即当前对象正处于哪个状态;主要有两个动作:一是状态初始化,一般只会有一次;二是当前状态的切换;
(4)PlayerState表示对象的一种状态(可继续细分),一般维护状态的某些信息,如状态名称等;还要获得Player对象和PlayerStateMachine对象用于在执行某些动作时方便调用,例如当Player对象的某个属性满足条件时,进行切换当前状态的操作。主要的动作有三个方面:一是进入状态是干什么;二是处于当前状态时需要一直重复干什么;三是退出当前状态是需要干什么(例如重置某些属性的数值等);
以下是代码:
PlayerState.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class PlayerState
{
protected PlayerStateMachine stateMachine;
protected Player player;
private string animBoolName;
public PlayerState(PlayerStateMachine stateMachine, Player player, string animBoolName)
{
this.stateMachine = stateMachine;
this.player = player;
this.animBoolName = animBoolName;
}
public virtual void Enter()
{
Debug.Log("I enter " + animBoolName);
}
public virtual void Update()
{
Debug.Log("I'm in " + animBoolName);
}
public virtual void Exit()
{
Debug.Log("I exit " + animBoolName);
}
}
PlayerIdleState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerIdleState : PlayerState
{
public PlayerIdleState(PlayerStateMachine stateMachine, Player player, string animBoolName) : base(stateMachine, player, animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (Input.GetKeyDown(KeyCode.N))
stateMachine.ChangeState(player.moveState);
}
}
PlayerMoveState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoveState : PlayerState
{
public PlayerMoveState(PlayerStateMachine stateMachine, Player player, string animBoolName) : base(stateMachine, player, animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (Input.GetKeyDown(KeyCode.N))
stateMachine.ChangeState(player.idleState);
}
}
PlayerStateMachine.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerStateMachine
{
public PlayerState currentState { get; private set; }
public void Initiallize(PlayerState _startState)
{
currentState = _startState;
currentState.Enter();
}
public void ChangeState(PlayerState _newState)
{
currentState.Exit();
currentState = _newState;
currentState.Enter();
}
}
Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public PlayerStateMachine stateMachine { get; private set; }
public PlayerIdleState idleState { get; private set; }
public PlayerMoveState moveState { get; private set; }
private void Awake()
{
stateMachine = new PlayerStateMachine();
idleState = new PlayerIdleState(stateMachine, this, "Idle");
moveState = new PlayerMoveState(stateMachine, this, "Move");
}
private void Start()
{
stateMachine.Initiallize(idleState);
}
private void Update()
{
stateMachine.currentState.Update();
}
}
希望本文对您有所帮助~