【Unity】Animancer状态机源码学习笔记(三)——StateChange
核心代码
1 | public struct StateChange<TState> : IDisposable |
简介
使用:该结构体只有在转换状态的时候才会创建,并且在转换完成后销毁(但身为静态成员的_current依然存在)
作用:
规范状态转换方法:在调用
IState
的方法时,都需要在该结构体的作用域中。换言之,可以在IState
的方法中访问上一个状态和下一个状态主要作用:在执行嵌套循环时,能正确的返回上一层
StateChange
的数据
使用示例
下面将根据示例来展示StateChange
的工作原理
规范状态转换方法
在StateMachine
中已经封装好了StateChange
的创建,所以我们可以直接在IState
的方法中访问StateChange
的数据
1 | public class AttackState : State |
嵌套访问
假设当前从FallState
->RunState
,为方便测试,以下代码并不规范
1 | public class RunState : State |
上方的嵌套可以表示成
1 | using (new StateChange<TState>(stateMachine, FallState, RunState)) |
状态的改变顺序
FallState
->RunState
RunState
->DefaultState
DefaultState
->HitState
- 最终的状态为
HitState
- 其实这是一个错误示范,若
TrySetDefaultState
返回true
,则应该return
如果在进入其他状态后没有return就会出现一个奇怪的问题:
第二层嵌套一号
已经退出RunState
了,但是不使用renturn,继续执行第一层时,_stateMachine.PreviousState
会变回成RunState
注意:
- 在成功进入其他状态后需要return
- 为了方便研究工作原理,我的所有状态继承的并不是
StateBehaviour
,而是最基础的State
,如果查看StateBehaviour
源码就能发现:真正进入状态才会执行的是OnEnable()
方法,而不是OnEnterState()
(该方法可以看做是一个工具人,用来判断是否满足进入状态的条件,实际上并没有进入)。
所以如果以上状态继承的是StateBehaviour
,发生上面的改变顺序时,并不会执行DefaultState.OnEnable()
。
嵌套访问实现原理
主要通过using
作用域、 StateChange()
构造函数和Dispose()
实现
假设当前正在执行上面示例的第二层嵌套一号
1 | public void ForceSetState(TState state) |
构造函数:
1 | internal StateChange(StateMachine<TState> stateMachine, TState previousState, TState nextState) |
Dispose
:
1 | public void Dispose() |
总结
从这次的学习中,已经非常熟悉这套状态机的工作原理了,最需要注意的如下:
- 如果继承的是
StateBehaviour
,规范的写法为OnEnterState()
用来判断能否进入状态OnEnable()
才是进入状态后真正需要执行的代码
- 如果成功切换状态则需要
return
,避免再执行后续代码,导致又退出刚进入的状态 - 虽然Animancer已经将
StateChange
封装好了,但我们还是得搞清楚它工作的作用:- 在
IState
的方法中,可以访问改变状态的参数 - 在嵌套访问
IState
时,返回上一层嵌套可以复原状态
- 在