前言
在 Unity3D 中实现状态管理器(State Management)可以通过 状态模式(State Pattern) 实现,帮助管理游戏对象或系统的不同状态(如角色移动、攻击、死亡等)。以下是一个通用的状态管理器实现方案,包含代码示例和详细说明:
对惹,这里有一 个游戏开发交流小组 ,希望大家可以点击进来一起交流一下开发经验呀!
1. 状态基类(State Base Class)
所有具体状态的基类,定义状态的生命周期方法:
csharp
public abstract class State
{
// 进入状态时调用
public virtual void OnEnter() { }
// 每帧更新时调用
public virtual void OnUpdate() { }
// 物理更新时调用
public virtual void OnFixedUpdate() { }
// 退出状态时调用
public virtual void OnExit() { }
}
2. 状态管理器(State Machine)
管理状态的切换和执行:
csharp
public class StateMachine : MonoBehaviour
{
private Dictionary<System.Type, State> _states = new Dictionary<System.Type, State>();
private State _currentState;
// 注册状态
public void RegisterState<T>(T state) where T : State
{
_states[typeof(T)] = state;
}
// 切换到指定状态
public void SwitchTo<T>() where T : State
{
if (_currentState != null)
{
_currentState.OnExit();
}
if (_states.TryGetValue(typeof(T), out State newState))
{
_currentState = newState;
_currentState.OnEnter();
}
else
{
Debug.LogError($"State {typeof(T)} not registered!");
}
}
// Unity 生命周期方法
private void Update()
{
_currentState?.OnUpdate();
}
private void FixedUpdate()
{
_currentState?.OnFixedUpdate();
}
}
3. 具体状态实现(Concrete States)
定义具体的状态类,例如 IdleState
、MoveState
:
IdleState.cs
csharp
public class IdleState : State
{
public override void OnEnter()
{
Debug.Log("Enter Idle State");
// 播放待机动画、重置计时器等
}
public override void OnUpdate()
{
// 检测输入或其他条件,切换到移动状态
if (Input.GetKeyDown(KeyCode.W))
{
// 通过状态管理器切换状态
GetComponent<StateMachine>().SwitchTo<MoveState>();
}
}
public override void OnExit()
{
Debug.Log("Exit Idle State");
}
}
MoveState.cs
csharp
public class MoveState : State
{
public override void OnEnter()
{
Debug.Log("Enter Move State");
// 播放移动动画、初始化移动参数
}
public override void OnUpdate()
{
// 处理移动逻辑
float moveSpeed = 5f;
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(horizontal, 0, vertical) * moveSpeed * Time.deltaTime;
transform.Translate(movement);
// 检测停止条件
if (Input.GetKeyUp(KeyCode.W))
{
GetComponent<StateMachine>().SwitchTo<IdleState>();
}
}
}
4. 在 Unity 中使用
将状态管理器挂载到游戏对象(如角色),并注册状态:
csharp
public class PlayerController : MonoBehaviour
{
private StateMachine _stateMachine;
private void Start()
{
_stateMachine = gameObject.AddComponent<StateMachine>();
// 注册状态
_stateMachine.RegisterState(new IdleState());
_stateMachine.RegisterState(new MoveState());
// 初始状态
_stateMachine.SwitchTo<IdleState>();
}
}
5. 高级扩展
状态间参数传递
通过 SwitchTo
方法传递参数:
csharp
public void SwitchTo<T>(object parameters) where T : State
{
// 在状态类的 OnEnter 中解析参数
}
// 在状态类中:
public override void OnEnter(object parameters)
{
if (parameters is int intParam)
{
// 使用参数
}
}
全局状态机
通过单例模式实现全局访问:
csharp
public class GameStateMachine : MonoBehaviour
{
public static GameStateMachine Instance { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
状态转换条件
在状态类中定义转换逻辑:
csharp
public class AttackState : State
{
public override void OnUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// 切换到防御状态
GetComponent<StateMachine>().SwitchTo<DefendState>();
}
}
}
总结
通过状态模式实现状态管理器的优点:
- 解耦:每个状态的逻辑独立,便于维护。
- 可扩展:新增状态只需继承基类。
- 易调试:状态切换清晰可见。
此方案适用于角色控制、UI 流程、游戏全局状态(如暂停、菜单)等场景。
更多教学视频