天天看点

从相机发出的射线

原文链接:从相机发出的射线

在[理解视锥]

      • Raycasting
      • 沿着一条射线移动相机

(https://docs.unity3d.com/Manual/UnderstandingFrustum.html)部分中,解释了相机视图中每个点都对应世界空间中的一条线。对这条线进行数学表达有时候很有用,Unity使用Ray对象的形式提供这个功能。射线总是对应视图中的一个点,因此Camera类提供了ScreenPointToRay和ViewPointToRay函数。两者的区别是,ScreenPointToRay接收以像素形式提供的点坐标,而ViewportPointToRay接收归一化后的坐标(0代表视图的底部和左边,1代表视图的顶部和右边)。两者都返回一条射线,包含射线原点,和一个表示射线方向的向量。射线从近裁切平面发出,而不是相机的transform位置。

Raycasting

相机发出的射线最常见的用途,是向场景中进行raycast。raycast从原点沿着射线方向发出想象的“激光束”,直到碰到场景中的collider。碰撞物体的信息和碰撞点的信息会在一个RaycastHit对象中返回。这在根据屏幕上的图像来定位一个物体时非常有用。比如当前鼠标位置处的物体可以使用下面的代码确定:

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public Camera camera;

    void Start(){
        RaycastHit hit;
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out hit)) {
            Transform objectHit = hit.transform;

            // Do something with the object that was hit by the raycast.
        }
    }
}
           

沿着一条射线移动相机

获取一个屏幕点对应的射线后,沿着射线移动相机的功能有时候很有用。比如说,想要根据用户当前选中的物体放大屏幕,同时保持物体固定在相同的屏幕位置(比如使用相机查看一个战术地图时也许有用)。实现这个功能的代码很简单:

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public bool zooming;
    public float zoomSpeed;
    public Camera camera;

    void Update() {
        if (zooming) {
            Ray ray = camera.ScreenPointToRay(Input.mousePosition);
            float zoomDistance = zoomSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
            camera.transform.Translate(ray.direction * zoomDistance, Space.World);
        }
    }
}