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

在Godot中通过鼠标检测并移动Physics2DServer的RID对象

检测鼠标悬停的RID刚体对象并实现拖拽(Godot)

需求描述

需要实现检测鼠标悬停对应的RID刚体对象,后续完成点击拖拽该对象的功能。目前想到的方案是创建一个跟随鼠标的RID碰撞体来检测碰撞,但希望了解更规范的直接通过鼠标获取目标RID的方式。

问题分析与规范解决方案

你尝试的intersect_point方法本身是规范的解决方案,但之前代码未生效的核心问题有两个:

  1. 创建RID刚体时错误使用了Physics2DServer.area_add_shape(这是给Area2D用的),刚体必须用Physics2DServer.body_add_shape添加形状;
  2. 参数配置可能存在冲突(比如碰撞层/掩码不匹配)。

修正后的RID刚体创建代码

func create_rigid_body(mouse_position: Vector2) -> RID:
    # 创建刚体RID
    var body_rid = Physics2DServer.body_create()
    Physics2DServer.body_set_mode(body_rid, Physics2DServer.BODY_MODE_RIGID)
    # 创建圆形碰撞形状
    var shape_rid = Physics2DServer.circle_shape_create()
    Physics2DServer.shape_set_data(shape_rid, 128)
    # 给刚体添加形状(必须用body_add_shape)
    Physics2DServer.body_add_shape(body_rid, shape_rid, Transform2D(1.0, mouse_position))
    # 将刚体加入当前场景的物理空间
    Physics2DServer.body_set_space(body_rid, get_world_2d().space)
    # 设置刚体初始位置
    Physics2DServer.body_set_state(body_rid, Physics2DServer.BODY_STATE_TRANSFORM, Transform2D(0, mouse_position))
    # 绑定力整合回调(用于后续拖拽或状态同步)
    Physics2DServer.body_set_force_integration_callback(body_rid, self, "_body_moved", 0)
    return body_rid  # 返回刚体RID而非形状ID,便于后续操作

鼠标悬停检测与RID获取代码

var hovered_body_rid: RID = null  # 记录当前悬停的刚体RID

func _input(event: InputEvent) -> void:
    # 处理鼠标移动事件,检测悬停
    if event is InputEventMouseMotion:
        var space_state = get_world_2d().get_direct_space_state()
        var mouse_pos = get_global_mouse_position()
        # 调用intersect_point检测鼠标位置的刚体
        var results = space_state.intersect_point(
            mouse_pos,
            1,          # 最多返回1个结果
            [],         # 排除的RID数组(可添加不需要检测的对象)
            0xFFFFFFFF, # 碰撞层掩码(全层检测)
            true,       # 检测刚体
            false       # 不检测Area
        )
        hovered_body_rid = results[0].rid if results.size() > 0 else null
        if hovered_body_rid:
            print("悬停刚体RID:", hovered_body_rid)
        else:
            print("无悬停刚体")
    
    # 处理鼠标点击,实现拖拽触发
    if event is InputEventMouseButton:
        if event.button_index == MOUSE_BUTTON_LEFT:
            if event.pressed and hovered_body_rid:
                # 这里可以启动拖拽逻辑,比如记录初始偏移
                print("开始拖拽刚体:", hovered_body_rid)
            else:
                # 停止拖拽
                print("结束拖拽")

拖拽实现思路

在拖拽过程中(鼠标按下并移动时),可以通过以下方式控制刚体位置:

func _process(delta: float) -> void:
    if hovered_body_rid and Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
        var target_pos = get_global_mouse_position()
        # 直接设置刚体位置(适合瞬时移动)
        Physics2DServer.body_set_state(
            hovered_body_rid,
            Physics2DServer.BODY_STATE_TRANSFORM,
            Transform2D(0, target_pos)
        )
        # 或者用施加力的方式实现平滑拖拽:
        # var current_pos = Physics2DServer.body_get_state(hovered_body_rid, Physics2DServer.BODY_STATE_TRANSFORM).origin
        # var force = (target_pos - current_pos) * 1000 * delta
        # Physics2DServer.body_apply_central_force(hovered_body_rid, force)

关于你之前的碰撞体方案

创建跟随鼠标的RID碰撞体来检测碰撞的方法是可行的,但属于冗余方案——intersect_point已经原生支持点位置的碰撞检测,额外创建碰撞体会增加不必要的性能开销,因此更推荐使用上述规范的点检测方法。

内容的提问来源于stack exchange,提问作者alex hernandez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:54:20