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

Godot 2D中如何从鼠标光标位置正确进行射线检测?

解决Godot 2D射线检测(鼠标悬停检测)问题

你的核心问题是射线起点和终点完全重合,长度为0的射线不可能检测到任何碰撞体。下面给你两种适配需求的解决方案:

方案1:直接检测鼠标位置的碰撞(推荐用于悬停检测)

如果只是要检测鼠标悬停的碰撞体,用IntersectPoint比射线检测更直接,不需要创建射线:

public override void _PhysicsProcess(double delta)
{
    var spaceState = GetWorld2D().DirectSpaceState;
    // 先把视口鼠标坐标转成世界坐标(相机缩放/平移时必须做这一步)
    Vector2 worldMousePos = GetViewport().GetCamera2D().UnprojectPosition(GetViewport().GetMousePosition());
    
    // 检测鼠标位置周围极小范围的碰撞体,radius设0.1足够
    var hitResults = spaceState.IntersectPoint(worldMousePos, 0.1f);
    if (hitResults.Count > 0)
    {
        GD.Print("检测到碰撞体:", hitResults[0]["collider"].Name);
    }
}

方案2:正确创建射线(适合穿透/方向检测)

如果确实需要用射线,要保证射线有有效长度,比如从相机后方发射到鼠标对应的世界位置:

public override void _PhysicsProcess(double delta)
{
    var spaceState = GetWorld2D().DirectSpaceState;
    Camera2D mainCamera = GetViewport().GetCamera2D();
    Vector2 viewportMousePos = GetViewport().GetMousePosition();
    
    // 射线起点:相机近平面的鼠标对应位置
    Vector2 rayStart = mainCamera.ProjectPosition(viewportMousePos, mainCamera.Near);
    // 射线终点:相机远平面的鼠标对应位置
    Vector2 rayEnd = mainCamera.ProjectPosition(viewportMousePos, mainCamera.Far);
    
    var rayQuery = PhysicsRayQueryParameters2D.Create(rayStart, rayEnd);
    // 可选:设置只检测特定碰撞层,比如只检测第2层
    // rayQuery.CollisionMask = 1 << 2;
    
    var hitResults = spaceState.IntersectRay(rayQuery);
    if (hitResults.Count > 0)
    {
        GD.Print("射线检测到:", hitResults[0]["collider"]);
    }
}

额外注意事项

  • 确保你的Area2D的Monitorable属性处于开启状态(默认开启,若手动关闭会无法被检测)
  • CollisionShape2D的Disabled属性要设为false,且形状范围正确
  • 永远不要忽略视口坐标到世界坐标的转换,尤其是相机有缩放、移动时,直接用GetMousePosition()得到的是像素坐标,不是世界空间的位置

内容的提问来源于stack exchange,提问作者Hulda Gnodima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:10:14