Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / StateController.cs
@小李xl 小李xl on 18 Nov 2022 3 KB Ai状态机调整
  1. using System;
  2. using Godot;
  3. using System.Collections.Generic;
  4.  
  5. /// <summary>
  6. /// 对象状态机控制器
  7. /// </summary>
  8. public class StateController<T, S> : Component where T : ActivityObject where S : Enum
  9. {
  10. /// <summary>
  11. /// 当前活跃的状态
  12. /// </summary>
  13. public IState<T, S> CurrState => _currState;
  14. private IState<T, S> _currState;
  15. /// <summary>
  16. /// 负责存放状态实例对象
  17. /// </summary>
  18. private readonly Dictionary<S, IState<T, S>> _states = new Dictionary<S, IState<T, S>>();
  19.  
  20. /// <summary>
  21. /// 记录下当前帧是否有改变的状态
  22. /// </summary>
  23. private bool _isChangeState;
  24. public override void PhysicsProcess(float delta)
  25. {
  26. _isChangeState = false;
  27. if (CurrState != null)
  28. {
  29. CurrState.PhysicsProcess(delta);
  30. //判断当前帧是否有改变的状态, 如果有, 则重新调用 PhysicsProcess() 方法
  31. if (_isChangeState)
  32. {
  33. PhysicsProcess(delta);
  34. }
  35. }
  36. }
  37.  
  38. /// <summary>
  39. /// 往状态机力注册一个新的状态
  40. /// </summary>
  41. public void Register(IState<T, S> state)
  42. {
  43. if (GetStateInstance(state.StateType) != null)
  44. {
  45. GD.PrintErr("当前状态已经在状态机中注册:", state);
  46. return;
  47. }
  48. state.Master = ActivityObject as T;
  49. state.StateController = this;
  50. _states.Add(state.StateType, state);
  51. }
  52.  
  53. /// <summary>
  54. /// 立即切换到下一个指定状态, 并且这一帧会被调用 PhysicsProcess
  55. /// </summary>
  56. public void ChangeState(S next, params object[] arg)
  57. {
  58. _changeState(false, next, arg);
  59. }
  60.  
  61. /// <summary>
  62. /// 切换到下一个指定状态, 下一帧才会调用 PhysicsProcess
  63. /// </summary>
  64. public void ChangeStateLate(S next, params object[] arg)
  65. {
  66. _changeState(true, next, arg);
  67. }
  68.  
  69. /// <summary>
  70. /// 根据状态类型获取相应的状态对象
  71. /// </summary>
  72. private IState<T, S> GetStateInstance(S stateType)
  73. {
  74. _states.TryGetValue(stateType, out var v);
  75. return v;
  76. }
  77.  
  78. /// <summary>
  79. /// 切换状态
  80. /// </summary>
  81. private void _changeState(bool late, S next, params object[] arg)
  82. {
  83. if (_currState != null && _currState.StateType.Equals(next))
  84. {
  85. return;
  86. }
  87. var newState = GetStateInstance(next);
  88. if (newState == null)
  89. {
  90. GD.PrintErr("当前状态机未找到相应状态:" + next);
  91. return;
  92. }
  93. if (_currState == null)
  94. {
  95. _currState = newState;
  96. newState.Enter(default, arg);
  97. }
  98. else if (_currState.CanChangeState(next))
  99. {
  100. _isChangeState = !late;
  101. var prev = _currState.StateType;
  102. _currState.Exit(next);
  103. GD.Print("nextState => " + next);
  104. _currState = newState;
  105. _currState.Enter(prev, arg);
  106. }
  107. }
  108. }