Godot 4.4.1中玩家同时触多尖刺仅扣1条生命值的实现方法
解决Godot 4.4.1中玩家同时触碰多个尖刺重复扣血的问题
问题核心是:玩家同时进入多个尖刺的Area2D时,每个尖刺的_on_body_entered事件会在同一帧内触发,导致多次扣血。你之前尝试的无敌机制没生效,大概率是因为无敌状态的设置存在延迟,没来得及阻止同一帧内的其他触发。以下是几个更优的解决方案:
方案1:让玩家统一处理受伤逻辑(推荐)
把扣血和无敌状态的管理从尖刺转移到玩家身上,确保同一帧内无论触发多少次受伤请求,玩家只会响应一次。
玩家脚本(Player.gd)
extends CharacterBody2D var is_invulnerable := false const INVULNERABILITY_DURATION := 1.5 # 无敌持续时间,可根据需求调整 func take_damage() -> void: if not is_invulnerable: # 扣血 Global.lifes -= 1 # 立刻开启无敌 is_invulnerable = true # 启动计时器恢复正常状态 $InvulnerabilityTimer.start() # 绑定Timer节点的timeout信号 func _on_invulnerability_timer_timeout() -> void: is_invulnerable = false
尖刺脚本修改
extends Area2D func _on_body_entered(body: Node2D) -> void: if body.is_in_group("Player"): # 调用玩家的受伤函数,由玩家自己判断是否扣血 body.take_damage()
注意:需要在玩家节点下添加一个Timer节点(命名为InvulnerabilityTimer),将其Wait Time设为INVULNERABILITY_DURATION,并勾选One Shot。
方案2:优化全局无敌状态的触发时机
如果你坚持使用全局状态管理无敌,需要确保扣血后立刻设置无敌状态,阻止同一帧内的其他尖刺触发。
尖刺脚本修改
extends Area2D func _on_body_entered(body: Node2D) -> void: if body.is_in_group("Player") and not Global.immortality: Global.lifes -= 1 # 立刻开启全局无敌,阻止后续触发 Global.immortality = true # 让玩家启动无敌计时器 body.start_invulnerability()
玩家脚本补充
extends CharacterBody2D const INVULNERABILITY_DURATION := 1.5 func start_invulnerability() -> void: $InvulnerabilityTimer.start() func _on_invulnerability_timer_timeout() -> void: Global.immortality = false
方案3:合并相邻尖刺的碰撞区域(备选)
如果你的尖刺是连续排列的,可以将多个尖刺的Area2D合并为一个,这样无论玩家碰多少个尖刺,只会触发一次_on_body_entered事件。但如果尖刺分散布局,这个方案操作成本较高,仅推荐用于连续尖刺场景。
内容的提问来源于stack exchange,提问作者Charles Dev
相关产品推荐
相关产品推荐

