В секции Основные сведения об усечённой пирамиде видимости было рассказано, что любая точка в поле зрения камеры соответствует линии в мировом пространстве. Иногда полезно иметь математическое представление этой линии и Unity может предоставить его в виде объекта Ray (луч). Ray всегда соответствует точке в поле зрения, потому класс Camera предоставляет методы ScreenPointToRay и ViewportPointToRay. Различие между ними в том, что ScreenPointToRay ожидает точку в виде пиксельных координат, в то время как ViewportPointToRay получает нормализованные координаты в диапазоне от 0 до 1 (где 0 представляет нижнюю или левую, а 1 - верхнюю или правую часть поля зрения). Каждая из этих функций возвращает Ray, который состоит из точки испускания (начала) и вектора, показывающего направление линии из этой точки. Ray берёт начало из ближней плоскости отсечения вместо точки transform.position камеры.
Луч из камеры чаще всего используют для совершения рейкаста в сцену. Рейкаст отправляет воображаемый “лазерный луч” вдоль программного луча из точки испускания до тех пор, пока он не встретит на пути коллайдер в сцене. В результате столкновения с коллайдером, возвращается 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);
}
}
}