在Godot中通过鼠标检测并移动Physics2DServer的RID对象
检测鼠标悬停的RID刚体对象并实现拖拽(Godot)
需求描述
需要实现检测鼠标悬停对应的RID刚体对象,后续完成点击拖拽该对象的功能。目前想到的方案是创建一个跟随鼠标的RID碰撞体来检测碰撞,但希望了解更规范的直接通过鼠标获取目标RID的方式。
问题分析与规范解决方案
你尝试的intersect_point方法本身是规范的解决方案,但之前代码未生效的核心问题有两个:
- 创建RID刚体时错误使用了
Physics2DServer.area_add_shape(这是给Area2D用的),刚体必须用Physics2DServer.body_add_shape添加形状; - 参数配置可能存在冲突(比如碰撞层/掩码不匹配)。
修正后的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
相关产品推荐
相关产品推荐

