limbo hsm

This commit is contained in:
2026-10-15 16:56:45 +08:00
parent 18e7b2daa8
commit a76c4aebef
30 changed files with 665 additions and 121 deletions
+22 -5
View File
@@ -1,3 +1,4 @@
class_name Player
extends CharacterBody3D
## 玩家协调器:只做三件事 —— 多人权限、依赖注入、按固定顺序编排各组件。
##
@@ -6,8 +7,12 @@ extends CharacterBody3D
## Motor 移动跳跃 character/player/player_motor.gd
## Pickup 拾取 character/player/player_pickup.gd
## Animator 动画表现 character/player/player_animator.gd(挂在 AnimationPlayer 上)
## HSM 状态机 character/player/hsm/(LimboAI LimboHSM,MANUAL 模式)
##
## 本脚本不实现任何操作,只负责「谁先谁后」和「谁有权跑」。
## 「玩家处于什么状态」(走 / 跑 / 蹲 / 跳 / 落)的判定完全在 HSM 里:
## 状态在 _enter 时写 motor.target_speed、motor.crouching/sprinting 和动画片段,
## 这里只按固定顺序推进各组件。
@onready var body: Node3D = $Body
## 本地玩家自己的模型(鼠)。第一人称要藏掉它,见 _ready()。
@@ -22,6 +27,9 @@ extends CharacterBody3D
@onready var look: PlayerLook = $Look
@onready var motor: PlayerMotor = $Motor
@onready var pickup: PlayerPickup = $Pickup
## LimboAI 层级状态机。update_mode = MANUAL,由 _physics_process 按管线顺序显式推进,
## 保证它永远排在 motor.step 之前、且只在权威端跑。
@onready var hsm: LimboHSM = $HSM
func _ready() -> void:
@@ -60,6 +68,12 @@ func _ready() -> void:
pickup.interact_state_changed.connect(_on_pickup_interact_state_changed)
# 调试面板接线:把要读的组件注入进去,面板自己不 get_node。
debug_panel.setup(self, motor, pickup, camera)
# 状态机接线:initialize 递归调所有状态的 _setup(注册各自的转换表),
# set_active 进入 initial_state(Grounded 会按当下输入挑子状态)。
# 只在权威端跑 —— 远端玩家由 Sync 复制 position / anim_state / anim_speed,
# 不需要也不允许本地再跑一套状态机;HSM 是 MANUAL 模式,不初始化就完全惰性。
hsm.initialize(self)
hsm.set_active(true)
set_mouse_captured(true)
@@ -91,13 +105,16 @@ func _on_pickup_interact_state_changed(hovering: bool, holding: bool) -> void:
func _physics_process(delta: float) -> void:
# 顺序固定:算速度 → 同步蹲伏高度 → 推进 → 播动画 → 搬物体。
# 由根节点统一编排,各组件自己不许写 _physics_process ——
# 顺序固定:状态机(判定状态,写目标速度与动画)→ 算速度 → 同步蹲伏高度 →
# 推进 → 刷步频 → 搬物体。由根节点统一编排,各组件自己不许写 _physics_process ——
# 否则顺序取决于节点树顺序,改个节点位置就会出现「先滑再算速度」这类隐形 bug。
# HSM 排最前:状态写入的 target_speed 当帧就被 motor 消费;
# 起跳在 Grounded 状态里就地执行(motor.try_jump),同一帧转进 Jump。
hsm.update(delta)
motor.step(delta)
# 蹲伏状态由 Motor 单点判定,再转交给 Look 去升降摄像机 ——
# 不让 Look 自己去读蹲键,免得两个组件各判一次、将来不同步。
# 蹲伏事实由 HSM 的 Crouch/Sneak 状态写进 motor.crouching ——
# 不让 Look 自己去读蹲键,免得两边各判一次、将来不同步。
look.set_crouching(motor.crouching)
move_and_slide()
animation_player.set_motion(velocity, is_on_floor(), motor.sprinting, motor.crouching)
animation_player.set_gait(velocity)
pickup.physics_step()