You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动