如何在Godot中通过鼠标坐标控制3D球体对象移动?
实现Godot中鼠标控制3D球体移动的方案
没问题,我帮你搞定这个鼠标控制球体移动的需求!下面用GDScript给出最常用的实现方式,也附带C#版本供你参考。
核心思路
我们需要捕获鼠标的相对移动量,将其映射到3D空间的X轴(左右)和Z轴(前后)移动上:
- 鼠标右移 → 球体沿X轴正方向移动
- 鼠标左移 → 球体沿X轴负方向移动
- 鼠标上移 → 球体沿Z轴负方向(Godot默认相机"前方")移动
- 鼠标下移 → 球体沿Z轴正方向移动
同时需要锁定鼠标在窗口内,这样才能持续获取相对移动输入。
GDScript实现步骤
1. 搭建基础场景
创建一个3D场景,添加:
- 一个
MeshInstance3D,将其Mesh设置为SphereMesh(调整大小到合适值) - 给
MeshInstance3D附加一个脚本(右键→Attach Script)
2. 完整脚本代码
extends MeshInstance3D # 控制球体移动速度,可根据需求调整 @export var move_speed: float = 6.0 func _ready(): # 捕获鼠标,使其锁定在窗口内(隐藏光标,持续获取移动输入) Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) func _physics_process(delta: float) -> void: # 获取鼠标的相对移动量(x=左右,y=上下) var mouse_delta: Vector2 = Input.get_last_mouse_speed() # 将鼠标移动映射到3D空间方向 var move_dir: Vector3 = Vector3( mouse_delta.x, # 左右对应X轴 0, # 不控制Y轴移动 mouse_delta.y # 上下对应Z轴(Godot默认前为-Z,刚好匹配鼠标y的正负) ) # 计算最终移动量并更新位置 var movement: Vector3 = move_dir * move_speed * delta global_position += movement func _input(event: InputEvent) -> void: # 按ESC键恢复鼠标可见,方便退出操作 if event is InputEventKey and event.keycode == KEY_ESCAPE: Input.set_mouse_mode( Input.MOUSE_MODE_VISIBLE if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED else Input.MOUSE_MODE_CAPTURED )
3. 进阶优化(如果需要物理碰撞)
如果你的球体需要和场景中的其他物体产生碰撞,建议把MeshInstance3D换成CharacterBody3D,然后修改移动逻辑为:
# 替换_physics_process里的移动代码 var movement: Vector3 = move_dir * move_speed * delta move_and_slide(movement, Vector3.UP)
这样球体就能自动处理碰撞和地面贴合逻辑了。
C#版本参考
如果你习惯用C#开发,这里是对应的实现代码:
using Godot; public partial class SphereController : MeshInstance3D { [Export] public float MoveSpeed = 6.0f; public override void _Ready() { Input.MouseMode = Input.MouseModeEnum.Captured; } public override void _PhysicsProcess(double delta) { Vector2 mouseDelta = Input.GetLastMouseSpeed(); Vector3 moveDir = new Vector3(mouseDelta.X, 0, mouseDelta.Y); Vector3 movement = moveDir * MoveSpeed * (float)delta; GlobalPosition += movement; } public override void _Input(InputEvent @event) { if (@event is InputEventKey keyEvent && keyEvent.Keycode == Key.Escape) { Input.MouseMode = Input.MouseMode == Input.MouseModeEnum.Captured ? Input.MouseModeEnum.Visible : Input.MouseModeEnum.Captured; } } }
注意事项
Input.get_last_mouse_speed()返回的是鼠标在一帧内的移动像素量,所以不需要额外归一化,直接乘以速度即可- 如果觉得移动太快/太慢,调整
move_speed参数就行 - 测试时记得运行场景,鼠标会被锁定,按ESC可以恢复
内容的提问来源于stack exchange,提问作者Wetsy




