Godot中CharacterBody3D.get_slide_collision()返回同一实例重复碰撞问题
关于Godot 4中move_and_slide()单次调用返回同一对象多次碰撞的问题
这是预期行为吗?
是的,这种情况属于move_and_slide()的预期行为。move_and_slide()的核心逻辑是在单次物理帧内,对角色的移动路径进行多次碰撞检测与位置修正——比如当角色碰撞到物体后,会沿着碰撞法线滑动,这个滑动过程中可能会再次触发与同一对象的碰撞检测。尤其是当角色碰撞体和敌人碰撞网格存在多个接触点,或者角色在着陆瞬间的移动轨迹导致碰撞检测被多次触发时,就会生成多条指向同一collider的碰撞记录。
需要自行处理重复碰撞吗?
需要。引擎不会自动合并同一对象的碰撞记录,所以开发者需要手动添加去重逻辑,避免对同一对象重复执行处理代码(比如多次加分)。
解决方案示例
可以用一个Set来记录已经处理过的碰撞对象,遍历碰撞列表时跳过已处理的实例:
func _physics_process(delta): # 先执行move_and_slide move_and_slide(target_velocity, Vector3.UP) var processed_mobs = Set[Node3D]() # 存储已处理的敌人实例 for index in range(get_slide_collision_count()): var collision = get_slide_collision(index) var collider = collision.get_collider() if collider == null or not collider.is_in_group("mob"): continue # 检查是否已处理过该敌人 if collider in processed_mobs: continue # 验证是否是从上方踩踏 if Vector3.UP.dot(collision.get_normal()) > 0.1: collider.squash() # 执行踩踏逻辑(加分) target_velocity.y = bounce_impulse processed_mobs.add(collider) # 标记为已处理
额外注意事项
- 确保敌人的
collision.squash()方法内部没有重复加分的逻辑(比如如果方法本身没做执行次数限制,即使只调用一次也没问题,但这里是多次调用导致的问题,所以去重是关键)。 - 若敌人使用了多个碰撞体组件,也可能导致同一实例产生多条碰撞记录,这种情况同样可以用上述去重逻辑解决。
内容的提问来源于stack exchange,提问作者asheath
相关产品推荐
相关产品推荐

