如何用KinematicBody2D制作可碰撞移动平台:解决随动与穿模问题
解决方案:KinematicBody2D 实现可穿透+带动玩家的悬浮平台
一、修复平台带动玩家移动的问题
两个KinematicBody2D碰撞时,move_and_slide会相互阻挡,导致平台停止移动。我们需要让平台移动后主动同步接触玩家的位移:
修改平台代码
extends KinematicBody2D export var levitation_speed: float = 1000 var _velocity: Vector2 var _last_position: Vector2 func _ready(): _last_position = position func _physics_process(delta): _velocity += levitation_speed * delta * Vector2.UP _velocity = move_and_slide(_velocity) # 计算平台本次移动的位移量 var movement = position - _last_position if movement.length_squared() > 0: # 遍历所有接触的玩家,同步位移 for body in get_colliding_bodies(): if body is Humanoid: body.position += movement _last_position = position
玩家代码优化(可选)
在玩家逻辑中加入平台速度继承,减少移动卡顿:
extends KinematicBody2D class_name Humanoid var velocity:Vector2 export var gravity_speed=3500 export var jump_speed=-1800 export var horizontal_speed=600 func _physics_process(delta): var direction=Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left") velocity.x=horizontal_speed * direction if(is_on_floor()): # 继承平台的移动速度 for body in get_colliding_bodies(): if body is KinematicBody2D: velocity += body._velocity if(Input.is_action_just_pressed("ui_up")): velocity.y+=jump_speed velocity.y += gravity_speed * delta velocity=move_and_slide(velocity, Vector2.UP)
二、实现玩家从平台下方穿过的效果
通过动态切换碰撞掩码,只在玩家位于平台上方时启用碰撞:
平台代码补充穿透逻辑
extends KinematicBody2D export var levitation_speed: float = 1000 var _velocity: Vector2 var _last_position: Vector2 var _original_collision_mask: int # 保存原始碰撞配置 func _ready(): _last_position = position _original_collision_mask = collision_mask func _physics_process(delta): _velocity += levitation_speed * delta * Vector2.UP _velocity = move_and_slide(_velocity) # 同步玩家位移逻辑(同之前的代码) var movement = position - _last_position if movement.length_squared() > 0: for body in get_colliding_bodies(): if body is Humanoid: body.position += movement _last_position = position # 动态调整碰撞状态 var enable_collision = false for body in get_overlapping_bodies(): if body is Humanoid: # 判断玩家是否在平台上方(玩家底部Y ≤ 平台顶部Y) if body.global_position.y + body.get_rect().size.y <= global_position.y: enable_collision = true else: enable_collision = false break # 切换碰撞掩码:需要碰撞则恢复原始配置,否则关闭碰撞 collision_mask = _original_collision_mask if enable_collision else 0
注意事项
- 确保玩家与平台的碰撞层/掩码初始配置正确,能互相检测
- 使用
get_overlapping_bodies()而非get_colliding_bodies(),避免关闭碰撞后无法检测玩家位置
备选方案:改用RigidBody2D实现
若更倾向于物理引擎驱动,可将平台改为RigidBody2D:
平台代码(RigidBody2D)
extends RigidBody2D export var levitation_speed: float = 1000 func _physics_process(delta): # 施加持续向上的力实现悬浮 apply_central_force(Vector2.UP * levitation_speed) # 设置为运动模式,避免被玩家撞飞 mode = MODE_KINEMATIC
穿透效果实现
同样使用动态切换碰撞掩码的逻辑,在平台的_physics_process中检测玩家位置并调整碰撞状态即可。
内容的提问来源于stack exchange,提问作者Manas R. Makde
相关产品推荐
相关产品推荐

