如何禁用玩家Hurtbox碰撞时维持敌人抓取攻击状态
解决2D平台僵尸游戏抓取状态维持问题
针对你遇到的“禁用玩家Hurtbox后敌人立刻回到Idle状态”的问题,这里有几个实用的解决思路:
思路1:让敌人在抓取状态时忽略Hurtbox退出事件
核心是给敌人的状态机加一个抓取状态锁,进入抓取序列后,不再响应Hurtbox的退出信号,直到动作完成。
具体实现步骤:
- 在敌人的脚本中添加
is_grabbing布尔变量,初始为false。 - 当检测到玩家Hurtbox进入时,先判断
is_grabbing是否为false,如果是则切换到抓取状态,将is_grabbing设为true,同时通知玩家禁用Hurtbox。 - 原本处理Hurtbox退出的逻辑,加上
if not is_grabbing的判断,只有非抓取状态才切换回Idle/追击状态。 - 监听敌人抓取动画的
animation_finished信号,动画结束时把is_grabbing设为false,并恢复玩家的Hurtbox碰撞。
GDScript示例:
# 敌人脚本 var is_grabbing = false var target_player = null func _on_hurtbox_area_entered(hurtbox): if not is_grabbing: target_player = hurtbox.owner switch_to_grab_state() # 自定义的状态切换函数 is_grabbing = true target_player.disable_hurtbox() func _on_hurtbox_area_exited(hurtbox): if not is_grabbing: switch_to_chase_or_idle_state() # 自定义的状态切换函数 func _on_grab_animation_finished(): is_grabbing = false target_player.enable_hurtbox() target_player = null
# 玩家脚本 func disable_hurtbox(): $HurtboxCollisionShape2D.set_deferred("disabled", true) func enable_hurtbox(): $HurtboxCollisionShape2D.set_deferred("disabled", false)
思路2:给玩家加抓取状态标记,让其他敌人跳过抓取逻辑
不用直接禁用Hurtbox,而是给玩家加一个“被抓取中”的标记,其他敌人检测到这个标记时,不触发抓取流程。
具体实现步骤:
- 玩家脚本中添加
is_being_grabbed布尔变量,初始为false。 - 敌人检测到玩家Hurtbox进入时,先检查
player.is_being_grabbed,如果为true就不执行抓取逻辑;否则切换到抓取状态,并将玩家的is_being_grabbed设为true。 - 抓取动作完成后,再把玩家的
is_being_grabbed设为false。
GDScript示例:
# 玩家脚本 var is_being_grabbed = false # 敌人脚本 func _on_hurtbox_area_entered(hurtbox): var player = hurtbox.owner if not player.is_being_grabbed: switch_to_grab_state() player.is_being_grabbed = true # 如果仍需要禁用Hurtbox防止其他碰撞,可保留disable_hurtbox调用 func _on_grab_animation_finished(): target_player.is_being_grabbed = false # target_player.enable_hurtbox() # 如果之前禁用了的话
思路3:临时修改Hurtbox的碰撞层/掩码
不直接禁用碰撞形状,而是把玩家Hurtbox的碰撞层切换为只有当前抓取敌人能检测的专属层,其他敌人无法检测到,但当前敌人已经进入抓取状态,不受影响。
具体实现步骤:
- 在项目设置的碰撞层中,预留一个专属层(比如第5层,索引为4),仅给抓取状态的敌人设置检测该层。
- 玩家脚本中记录Hurtbox的原始碰撞层,被抓取时切换到专属层,抓取完成后切回原始层。
GDScript示例:
# 玩家脚本 var original_hurtbox_layer = 0 func _ready(): original_hurtbox_layer = $HurtboxCollisionShape2D.collision_layer func disable_hurtbox_for_grab(): # 切换到专属碰撞层(假设第5层,对应二进制1<<4) $HurtboxCollisionShape2D.collision_layer = 1 << 4 func enable_hurtbox_after_grab(): $HurtboxCollisionShape2D.collision_layer = original_hurtbox_layer
内容的提问来源于stack exchange,提问作者DeruDeru
相关产品推荐
相关产品推荐

