实体状态机设计(1)
使用节点式的方式来设计实体状态机
脚本部分分为
状态脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19状态类是所有状态的基类,提供基础的方法和切换信号
# state.gd
class_name State extends Node
# 切换状态的信号
signal switch_state(state: State)
func enter_state() -> void:
pass
func exit_state() -> void:
pass
func update(_delta: float) -> void:
pass
func physics_update(_delta: float) -> void:
pass状态机脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45状态机是管理状态的具体部分
包含初始化状态、记录当前状态、更新状态、更新物理状态
# state_machine.gd
class_name StateMachine extends Node
# 导出变量来存储初始化状态
# 当前状态的引用
var active_state: State:
set(new_value):
active_state = new_value
print("Changed to ",active_state.name)
# 在ready函数中遍历所有状态
# 把switch_state 与 change_state函数链接,由状态机来处理
func _ready() -> void:
for child_state: State in get_children():
child_state.switch_state.connect(change_state)
change_state(initial_state)
func _process(delta: float) -> void:
# 如果激活状态,更新状态
if active_state:
active_state.update(delta)
func _physics_process(delta: float) -> void:
if active_state:
active_state.physics_update(delta)
func change_state(new_state: State) -> void:
if new_state == active_state:
return
# 退出当前状态
if active_state:
active_state.exit_state()
# 配置为新状态
active_state = new_state
# 进入新状态
if active_state:
active_state.enter_state()动作脚本
1 | 以站立和行走状态为例,具体状态脚本有进入状态、触发更新状态信号两个部分 |
流程一:静止(Idle)切换到行走(Walk)
假设当前角色处于 Idle 状态,玩家按下了方向键。
| 步骤 | 执行位置 | 具体动作与代码逻辑 |
|---|---|---|
| 1. 输入检测 | Idle_state.gd |
引擎调用 active_state.update(delta),实际执行 Idle_state 的 update 方法。代码检测到输入向量 不等于 Vector2.ZERO。 |
| 2. 发起切换 | Idle_state.gd |
执行 switch_state.emit(walk_state)。注意:此时 Idle 并不知道状态机是谁,它只是把信号抛出去。 |
| 3. 信号拦截 | StateMachine.gd |
由于提前绑定了信号,状态机立刻捕获到这个信号,并调用 change_state(walk_state)。 |
| 4. 退出旧状态 | StateMachine.gd |
判断新旧状态不同,执行 active_state.exit_state(),即调用 Idle_state 的 exit_state(比如停止待机动画)。 |
| 5. 更新引用 | StateMachine.gd |
执行 active_state = new_state,此时激活状态变为 Walk,控制台打印 "Changed to Walk"。 |
| 6. 进入新状态 | StateMachine.gd |
执行 active_state.enter_state(),即调用 Walk_state 的 enter_state(比如播放行走动画)。 |
| 7. 下一帧生效 | - | 从下一帧开始,_process 和 _physics_process 透传的对象变成了 Walk_state,角色的移动逻辑正式开始。 |
流程二:行走(Walk)切换回静止(Idle)
假设当前角色处于 Walk 状态,玩家松开了所有方向键。
| 步骤 | 执行位置 | 具体动作与代码逻辑 |
|---|---|---|
| 1. 输入检测 | Walk_state.gd |
引擎调用 active_state.update(delta),执行 Walk_state 的 update。代码检测到输入向量 等于 Vector2.ZERO。 |
| 2. 发起切换 | Walk_state.gd |
执行 switch_state.emit(idle_state),请求切换回静止状态。 |
| 3. 信号拦截 | StateMachine.gd |
状态机再次捕获信号,调用 change_state(idle_state)。 |
| 4. 退出旧状态 | StateMachine.gd |
执行 active_state.exit_state(),调用 Walk_state 的 exit_state(停止走路粒子特效或脚步声)。 |
| 5. 更新引用 | StateMachine.gd |
active_state = idle_state,控制台打印 "Changed to Idle"。 |
| 6. 进入新状态 | StateMachine.gd |
执行 active_state.enter_state(),调用 Idle_state 的 enter_state(播放待机动画,重置呼吸参数等)。 |
| 7. 下一帧生效 | - | 下一帧起,_process 执行 Idle 的逻辑,角色停止移动。 |
未来会在这个状态机基底上,进行角色运动的设计