Table of Contents

射线检测

中级 程序员

Warning

Bullet Physics is being phased out. We no longer plan to support or expand its features as our focus shifts to Bepu Physics. We recommend transitioning to Bepu Physics for access to the latest updates and ongoing improvements.

射线检测(Raycasting) 会在场景中追踪一条不可见的直线,以找到相交的碰撞体。例如,这可用于检查哪些对象位于枪的射击路线上,或在用户点击时检查鼠标光标下方是什么。

Note

射线检测使用碰撞体来计算交点。它会忽略没有碰撞体组件的实体。更多信息请参见碰撞体。

要使用射线检测,请在当前 Simulation 中使用 Simulation.Raycast。

有关射线检测的示例,请参见 Stride 附带的 Physics Sample 项目。

示例代码

此代码从鼠标的屏幕位置发送一条射线检测:

public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera, Simulation simulation)
{
    Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);

    // 重构 (-1, +1) 范围内的投影空间位置。
    //    不要忘记在屏幕坐标中 Y 向下,但在投影空间中 Y 向上
    Vector3 sPos;
    sPos.X = screenPos.X * 2f - 1f;
    sPos.Y = 1f - screenPos.Y * 2f;

    // 计算射线检测的近端(起点)
    // 假设它具有相同的投影空间 (x,y) 坐标且 z = 0(位于近平面上)
    // 我们需要将它反投影到世界空间
    sPos.Z = 0f;
    var vectorNear = Vector3.Transform(sPos, invViewProj);
    vectorNear /= vectorNear.W;

    // 计算射线检测的远端(终点)
    // 假设它具有相同的投影空间 (x,y) 坐标且 z = 1(位于远平面上)
    // 我们需要将它反投影到世界空间
    sPos.Z = 1f;
    var vectorFar = Vector3.Transform(sPos, invViewProj);
    vectorFar /= vectorFar.W;

    // 从近平面上的点向远平面上的点执行射线检测并获取碰撞结果
    var result = simulation.Raycast(vectorNear.XYZ(), vectorFar.XYZ());
    return result.Succeeded;
}
Note

有多种方法可以从你的 ScriptComponent 内部获取这个 Simulation 的引用:

  • 推荐的方式是通过物理组件的引用,例如 myRigidBody.Simulation 或 myCollision.Simulation,这是最快的方式。
  • 其次是通过 SceneSystem,调用 SceneSystem.SceneInstance.GetProcessor<PhysicsProcessor>()?.Simulation。
  • 或者通过 this.GetSimulation(),注意这里的 this 是必需的,因为它是一个扩展方法。

另请参阅