You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:57:08