Управление камерой в Unity3D, используя мышку

Одна из первых проблем, вставших передо мной — показать игроку мир вокруг него.

Собственно, в Unity3D уже есть необходимые компоненты, которые просто можно «навесить» на объект, настроить параметры и всё будет работать…. К примеру, можно взять обычный Standart Assets -> MouseOrbit, или, например, скрипт Камера от третьего лица.

Но мы не ищем лёгких путей

Обращаю внимание, что в этой статье я «изобретаю велосипед» с целью познакомиться с элементарными операциями в Unity3D, изучения классов и операций с объектами. Поэтому, если Вы гуру программирования, то можете проходить мимо =)

Подготовка объектов.

Итак, начнём с того, что создадим какой-нибудь объект (например куб) и привяжем на него камеру (она у нас сейчас только одна — главная камера).

После этого создадим скрипт C#, и назовём его MoveMouse

Написание скрипта.

Изначально нужно было определить позицию мышки.

Это оказалось довольно просто — через класс Input и его параметр mousePosition, который содержит три координаты для каждой из осей — x, y и z.

Итак, заведём внутреннюю переменную MousePos, и будем сохранять в неё координаты текущей позиции мышки. Делать это лучше всего перед отрисовкой экрана в событии Update().

using UnityEngine;
using System.Collections;

public class MoveMouse : MonoBehaviour {
  private Vector3  MousePos;
  void Update () {
    MousePos = Input.mousePosition;
  }
}

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

При этом мы считаем, что камера привязана именно к тому объекту, вокруг которого будет вращаться. Поэтому ищем этот объект через связь «Родитель-потомок».

Незачем это делать каждый раз, а достаточно будет сделать при создании самой камеры на сцене:

 public  GameObject  go;
  private  Camera  goCamera;

  void Start(){
      // Инициализируем кординаты мышки и ищем главную камеру
    goCamera = camera;
    go    = goCamera.transform.parent.gameObject;
  }

Итак, у нас уже есть ссылка на камеру, которую будем крутить, ссылка на объект, вокруг которого будем крутить, и координаты мышки.

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

Узнать состояние клавиш мышки можно через всё тот-же класс Input. Специально для этого у него есть метод GetMouseButton.

Само перемещение камеры будем располагать в событии FixedUpdate():

void FixedUpdate () {
    if(Input.GetMouseButton(1)) {
      //
    }
  }

И наконец, мы подошли к самому интересному — определить угол поворота в зависимости от позиции мышки и повернуть камеру.

Коэффициент поворота определить довольно просто: определяем позицию мышки, отнимаем от неё координату середины экрана, и делим получившееся число на размер экрана (отдельно для оси Х и отдельно для Y).

К примеру, мышка находится на координате 852 по оси Х, а размер экрана по ширине равен 1024. Тогда, согласно формуле:

(852-1024)/1024=-0,16796875

Коэффициент -0,16796875 как раз и будет отвечать за угол поворота по оси Х.

  private float   MyAngle = 0F;

  void FixedUpdate () {
    if(Input.GetMouseButton(1)) {
    MyAngle = 0;
    MyAngle = ((MousePos.x-(Screen.width/2))/Screen.width);
    }
  }

Угол мы рассчитали, теперь осталось только повернуть камеру.

Сделать это можно, используя метод RotateAround класса transform.

goCamera.transform.RotateAround(go.transform.position, goCamera.transform.up, MyAngle);

Примечание.

Внимательные читатели могли заметить, что ось, указанная для поворота по горизонтали указана goCamera.transform.up. Честно говоря, я не знаю почему так, но именно так оно работает.

И теперь то-же самое для поворота по вертикали:

 MyAngle = ((MousePos.y-(Screen.height/2))/Screen.height);
    goCamera.transform.RotateAround(go.transform.position, goCamera.transform.right, -MyAngle);

Вроде-бы можно и закругляться, но есть ещё один момент, который нужно учесть.

Пользователи всегда хотят настраиваемые параметры. И чувствительность мышки обычно стоит на одном из первых мест при настройке игры «под себя».

Давайте учтём это желание в нашем скрипте. Для этого введём параметр чувствительности sensitivity, и будем его использовать как коэффициент, влияющий на угол поворота:

    MyAngle = sensitivity*((MousePos.x-(Screen.width/2))/Screen.width);
    goCamera.transform.RotateAround(go.transform.position, Vector3.up, MyAngle);
    MyAngle = sensitivity*((MousePos.y-(Screen.height/2))/Screen.height);
    goCamera.transform.RotateAround(go.transform.position, Vector3.left, MyAngle);

Скрипт целиком.

Вот теперь точно всё, и осталось только показать весь скрипт целиком, с моими комментариями =)

using UnityEngine;
using System.Collections;

public class MoveMouse : MonoBehaviour {

  /// <summary>
  /// Скрипт управления камерой через мышку
  /// GameObject - объект, к которому привязана камера (вращаемся вокруг этого объекта)
  /// sensitivity - чувствительность мышки
  /// </summary>

  public GameObject go;
  public float   sensitivity = 1F;
  private Camera  goCamera;
  private Vector3  MousePos;
  private float   MyAngle = 0F;

  void Start(){
      // Инициализируем кординаты мышки и ищем главную камеру
    goCamera = camera;
    go    = goCamera.transform.parent.gameObject;
  }

  void Update () {
    MousePos = Input.mousePosition;
  }

  void FixedUpdate () {
    if(Input.GetMouseButton(1)) {
    MyAngle = 0;
      // расчитываем угол, как:
      // разница между позицией мышки и центром экрана, делённая на размер экрана
      //  (чем дальше от центра экрана тем сильнее поворот)
      // и умножаем угол на чуствительность из параметров
    MyAngle = sensitivity*((MousePos.x-(Screen.width/2))/Screen.width);
    goCamera.transform.RotateAround(go.transform.position, goCamera.transform.up, MyAngle);
    MyAngle = sensitivity*((MousePos.y-(Screen.height/2))/Screen.height);
    goCamera.transform.RotateAround(go.transform.position, goCamera.transform.right, -MyAngle);
  }
  }
}