Статьи

Unity3D: камеры от третьего лица

Камера является одним из самых важных элементов в 3D-игре. Он действует как глаза игрока, позволяя им видеть игровой мир с разных точек зрения. В Unity3D 3D-камера работает так же, как пленочная камера. Его можно панорамировать, наклонять и масштабировать для кадрирования сцен. Из этого туториала вы узнаете, как создавать несколько перспектив камеры от третьего лица.

Для вдохновения или для использования в качестве отправной точки для своей работы ознакомьтесь с некоторыми из самых популярных 3D-моделей на Envato Market. Или получите помощь один на один, выбрав один из сервисов 3D-дизайна и моделирования в Envato Studio.


Нам нужен простой проект для тестирования скриптов нашей камеры. Нам понадобится сцена с земной плоскостью, на которой есть текстура. Это позволит легко увидеть, как каждая камера движется и реагирует на входы игроков. Когда мы закончим, это должно выглядеть так:

Готовая сцена

Выполните следующие шаги для настройки проекта:

  1. Нажмите Файл> Новый проект
  2. Назовите папку вашего проекта Камеры от третьего лица
  3. Нажмите Создать
  4. Нажмите GameObject> Создать другой> Направленный свет
  5. Нажмите GameObject> Создать другое> Плоскость
  6. В Инспекторе найдите компонент Transform и измените положение X на 0, Y на -0.5 и Z на 0, чтобы он находился ниже куба
  7. Скачать grid.png
  8. Перетащите grid.png на панель «Проект».
  9. Перетащите текстуру сетки с панели проекта на плоскость на панели иерархии.
  10. Выберите основную камеру, переместите и поверните ее в положение над и за кубом
  11. Сохраните свою сцену (Файл> Сохранить сцену) и назовите ее Main

Все камеры, которые мы собираемся создать, будут нуждаться в цели: на что-то смотреть или следовать. Итак, давайте создадим основного игрока, которого мы можем перемещать с помощью клавиш со стрелками.

  1. Нажмите GameObject> Создать другое> Куб
  2. Переименовать его игрок
  3. В инспекторе убедитесь, что все координаты X, Y и Z установлены в ноль, поэтому мы уверены, что игрок находится в центре трехмерного мира.
  4. Нажмите Активы> Создать> C # Script
  5. Назовите скрипт Player
  6. Перетащите сценарий проигрывателя с панели «Проект» на проигрыватель на панели «Иерархия».

В сценарии Player добавьте два открытых свойства для движения и скорости поворота. Затем добавьте следующий код в ваш метод Update ():

01
02
03
04
05
06
07
08
09
10
11
12
public class Player : MonoBehaviour {
    public float movementSpeed = 10;
    public float turningSpeed = 60;
 
    void Update() {
        float horizontal = Input.GetAxis(«Horizontal») * turningSpeed * Time.deltaTime;
        transform.Rotate(0, horizontal, 0);
         
        float vertical = Input.GetAxis(«Vertical») * movementSpeed * Time.deltaTime;
        transform.Translate(0, 0, vertical);
    }
}

Это дает игроку управление, похожее на управление танком. Горизонтальная ось (клавиши «влево» или «вправо») вращают игрока, а вертикальная ось (клавиши «вверх» или «вниз») перемещает игрока вперед и назад.

Инспектор игрока

Это самая простая камера от третьего лица. Он находится в фиксированном месте в трехмерном мире и отслеживает свою цель, как турель.

  1. Нажмите Активы> Создать> C # Script
  2. Назовите скрипт LookAtCamera
  3. Перетащите скрипт LookAtCamera с панели «Проект» на основную камеру на панели «Иерархия».

В сценарии LookAtCamera создайте открытый атрибут для цели нашей камеры в верхней части класса. Открытые атрибуты доступны в Инспекторе и позволят нам назначить Player в качестве цели камеры:

1
2
public class LookAtCamera : MonoBehaviour {
   public GameObject target;

Далее нам нужно указать преобразование нашей камеры, чтобы посмотреть на целевой объект. К счастью, у объектов преобразования есть удобный метод LookAt (), который мы можем использовать для этого. Мы могли бы сделать это в методе Update (), но вместо этого мы создали метод LateUpdate (). Как правило, во всех сценариях камеры всегда следует использовать метод LateUpdate () вместо метода Update (). LateUpdate () происходит после завершения Update (), поэтому у сценария Player есть шанс закончить вычисление позиции игрока до того, как камера вычислит свою позицию. Это приводит к более плавному движению камеры:

1
2
3
void LateUpdate() {
    transform.LookAt(target.transform);
}

Финальный скрипт должен выглядеть так:

1
2
3
4
5
6
7
public class LookAtCamera : MonoBehaviour {
    public GameObject target;
     
    void LateUpdate() {
        transform.LookAt(target.transform);
    }
}

Если вы попытаетесь запустить игру сейчас, вы получите ошибки с жалобой на UnassignedReferenceException. Чтобы предотвратить это, перетащите Player с панели «Иерархия» и поместите его в свойство Target сценария в Инспекторе. У камеры теперь есть правильная цель для просмотра.

Перетащите игрока в инспектор

Это тип камеры, который вы обычно найдете в играх, таких как Diablo, также известная как игра «dungeon crawler». Камера находится над игроком и движется относительно персонажа, но никогда не вращается.

  1. Нажмите Активы> Создать> C # Script
  2. Назовите сценарий DungeonCamera
  3. Перетащите сценарий DungeonCamera с панели «Проект» на основную камеру на панели «Иерархия».

В сценарии DungeonCamera нам снова нужно создать открытый атрибут для цели нашей камеры. Нам также нужно создать переменную для хранения смещения между камерой и ее целью. Смещение представлено в виде вектора 3 и будет использоваться для сохранения относительного расстояния при перемещении игрока. Вы можете заметить, что мы не присваиваем смещению значение при первом его объявлении. Это потому, что мы будем вычислять значение при первом запуске скрипта. Мы можем использовать метод Start () для этого:

1
2
3
4
5
6
7
public class DungeonCamera : MonoBehaviour {
   public GameObject target;
   Vector3 offset;
 
   void Start() {
       offset = transform.position — target.transform.position;
   }

В каждом кадре нам нужно обновлять положение камеры в зависимости от положения игрока, применяя смещение. Как обычно, это должно быть сделано в методе LateUpdate ():

1
2
3
4
void LateUpdate() {
    Vector3 desiredPosition = target.transform.position + offset;
    tranform.position = desiredPosition;
}

Перетащите проигрыватель с панели «Иерархия» в свойство «Цель» сценария в Инспекторе.

Вы можете заметить, что движение камеры немного жесткое. Было бы неплохо немного ослабить движение, чтобы потребовалось некоторое время, чтобы догнать игрока. Мы можем сделать это, используя метод Vector3.Lerp () . Лерп линейно интерполирует между двумя точками, что означает, что он плавно переходит из одной точки в другую по прямой линии.

Lerp

Чтобы контролировать, насколько сильно применяется демпфирование, мы можем создать еще один публичный атрибут, который называется демпфированием!

1
public float damping = 1;

Две точки, между которыми мы можем перейти — текущая позиция камеры с примененным демпфированием и желаемая позиция без демпфирования.

1
2
3
4
void LateUpdate() {
   Vector3 desiredPosition = target.transform.position + offset;
   Vector3 position = Vector3.Lerp(transform.position, desiredPosition, Time.deltaTime * damping);
   transform.position = position;

Наконец, мы хотим, чтобы камера продолжала смотреть на игрока:

1
transform.LookAt(target.transform.position);

Финальный скрипт выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public class DungeonCamera : MonoBehaviour {
    public GameObject target;
    public float damping = 1;
    Vector3 offset;
 
    void Start() {
        offset = transform.position — target.transform.position;
    }
     
    void LateUpdate() {
        Vector3 desiredPosition = target.transform.position + offset;
        Vector3 position = Vector3.Lerp(transform.position, desiredPosition, Time.deltaTime * damping);
        transform.position = position;
 
        transform.LookAt(target.transform.position);
    }
}

Этот тип камеры обычно используется в играх-платформерах, таких как Mario Galaxy. Камера находится позади и над игроком и вращается вокруг персонажа, когда он поворачивается.

  1. Нажмите Активы> Создать> C # Script
  2. Назовите скрипт FollowCamera
  3. Перетащите скрипт FollowCamera с панели «Проект» на основную камеру на панели «Иерархия».

Как и в случае с камерой Dungeon Crawler, для камеры Follow требуется открытый атрибут для цели, а также смещение. Смещение должно быть установлено в методе Start ():

1
2
3
4
5
6
7
public class FollowCamera : MonoBehaviour {
   public GameObject target;
   Vector3 offset;
 
   void Start() {
       offset = target.transform.position — transform.position;
   }

Чтобы сориентировать камеру за целью, нам сначала нужно получить угол наклона цели и повернуть его во вращение в методе LateUpdate ():

1
2
3
void LateUpdate() {
   float desiredAngle = target.transform.eulerAngles.y;
   Quaternion rotation = Quaternion.Euler(0, desiredAngle, 0);

Затем мы можем умножить смещение на поворот, чтобы ориентировать смещение так же, как и цель. Затем мы вычитаем результат из позиции цели.

1
transform.position = target.transform.position — (rotation * offset);

Чтобы продолжать смотреть на игрока:

1
transform.LookAt(target.transform);

Перетащите проигрыватель с панели «Иерархия» в свойство «Цель» сценария в Инспекторе.

Следуйте за камерой

То же самое демпфирующее движение, которое мы применили к камере Dungeon, можно применить к камере Follow. Сначала мы добавим атрибут демпфирования, чтобы упростить настройку демпфирования:

1
public float damping = 1;

Вместо того, чтобы рыться между двумя точками, как мы делали с камерой Dungeon, мы будем рыться между углом камеры и углом цели. Поэтому вместо Vector3.Lerp () мы используем метод Mathf.LerpAngle () . Мы заменяем исходный код угла на:

1
2
3
4
float currentAngle = transform.eulerAngles.y;
float desiredAngle = target.transform.eulerAngles.y;
float angle = Mathf.LerpAngle(currentAngle, desiredAngle, Time.deltaTime * damping);
Quaternion rotation = Quaternion.Euler(0, angle, 0);

Финальный скрипт должен выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class FollowCamera : MonoBehaviour {
    public GameObject target;
    public float damping = 1;
    Vector3 offset;
     
    void Start() {
        offset = target.transform.position — transform.position;
    }
     
    void LateUpdate() {
        float currentAngle = transform.eulerAngles.y;
        float desiredAngle = target.transform.eulerAngles.y;
        float angle = Mathf.LerpAngle(currentAngle, desiredAngle, Time.deltaTime * damping);
         
        Quaternion rotation = Quaternion.Euler(0, angle, 0);
        transform.position = target.transform.position — (rotation * offset);
         
        transform.LookAt(target.transform);
    }
}

Этот тип камеры похож на камеру слежения, за исключением того, что вращение контролируется мышью, которая затем направляет персонажа в любом направлении, к которому обращена камера.

  1. Нажмите Активы> Создать> C # Script
  2. Назовите сценарий DungeonCamera
  3. Перетащите сценарий DungeonCamera с панели «Проект» на основную камеру на панели «Иерархия».

Как и камера Follow, камера Mouse Aim будет нуждаться в общедоступном атрибуте для цели и скорости вращения, а также смещения. Смещение должно быть установлено в методе Start ():

1
2
3
4
5
6
7
8
public class MouseAimCamera : MonoBehaviour {
   public GameObject target;
   public float rotateSpeed = 5;
   Vector3 offset;
 
   void Start() {
       offset = target.transform.position — transform.position;
   }

Мы можем получить доступ к горизонтальной оси мыши (он же Mouse X) и использовать ее для поворота цели.

1
2
float horizontal = Input.GetAxis(«Mouse X») * rotateSpeed;
target.transform.Rotate(0, horizontal, 0);

Затем мы ориентируем смещение в том же направлении и вычитаем его из положения цели, чтобы оставить камеру позади цели.

1
2
3
4
5
float desiredAngle = target.transform.eulerAngles.y;
Quaternion rotation = Quaternion.Euler(0, desiredAngle, 0);
transform.position = target.transform.position — (rotation * offset);
 
transform.LookAt(target.transform);

Перетащите проигрыватель с панели «Иерархия» в свойство «Цель» сценария в Инспекторе.

В отличие от других скриптов, мы не собираемся добавлять какое-либо демпфирование к движению камеры. Из-за точного характера мыши, это часто может привести к укачиванию.

Конечный скрипт должен выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public class MouseAimCamera : MonoBehaviour {
    public GameObject target;
    public float rotateSpeed = 5;
    Vector3 offset;
     
    void Start() {
        offset = target.transform.position — transform.position;
    }
     
    void LateUpdate() {
        float horizontal = Input.GetAxis(«Mouse X») * rotateSpeed;
        target.transform.Rotate(0, horizontal, 0);
 
        float desiredAngle = target.transform.eulerAngles.y;
        Quaternion rotation = Quaternion.Euler(0, desiredAngle, 0);
        transform.position = target.transform.position — (rotation * offset);
         
        transform.LookAt(target.transform);
    }
}

К одной камере можно одновременно применить несколько сценариев камеры. Чтобы переключаться между различными сценариями, включите нужный сценарий, отметив его и сняв отметку со всех остальных. Это может быть полезно для переключения на другой стиль камеры для создания снимков или вырезанных сцен.

Несколько камер в Инспекторе

Unity также поставляется с несколькими сценариями камеры, которые вы можете использовать прямо из коробки. Сценарии хорошо документированы, просты в настройке и являются отличными руководствами для создания и улучшения собственных сценариев камеры.

  1. Нажмите Активы> Пакет импорта> Сценарии
  2. Снимите все, кроме скриптов камеры
Импортный пакет

Unity позволяет легко создавать самые разные камеры для игр любого типа. С помощью всего лишь нескольких строк кода, самый важный элемент вашей игры готов к работе. В то время как некоторые могут найти математику немного пугающей, Unity предоставляет так много полезных вспомогательных функций, что большинство тяжелых вычислений уже сделано для вас.

Нажмите здесь, чтобы загрузить полный проект Unity.