Как сделать поворот в сторону мыши в unity

Обновлено: 04.07.2024

Здравствуйте, прошу помощи. Облазил весь интернет и ничего не нашел, либо нашел только какие-то обрывки кодов без объяснения. Суть в следующем: есть персонаж, есть камера привязанная к нему через инспектор объектов. Необходимо сделать так, чтобы камера поворачивалась с помощью мыши, как в FPS. Была успешная попытка, но с поворотом камеры поворачивался и сам персонаж, да и поворот был очень медленным. В интернете нет конкретной информации по этому поводу. Если найдутся здесь добрые люди, то хотелось бы попросить с подробными(на сколько это возможно) комментариями. P.S.: шутки, на тему "чайник", "в гугле забанили" и прочие, просьба оставить при себе. Если будете предоставлять какие-либо ссылки, то ОГРОМНАЯ просьба, чтобы эти ссылки не были на офф сайт, в котором только поверхностный пример того, как использовать тот или иной скрипт, и не на уроки от людей, которые делают скрипты именно для СВОИХ проектов. Заранее спасибо.

10 голосов , оценка 4.300 из 5

Сделать так, чтобы объект вращался вокруг своей оси очень просто, для этого есть функция Rotate. Кроме обычного вращения, еще можно сделать орбиту, по которой будет задано вращение относительно другого объекта, здесь поможет функция RotateAround, достаточно указать цель, ось и скорость. Но что если, нужно чтобы вращение управлялось с помощью мышки? Например, есть некая планета и надо, чтоб камера крутилась вокруг нее. Именно это мы попробуем реализовать в сегодняшнем скрипте. Дополнительно, сделаем небольшую модификацию, чтобы вращение какого-нибудь объекта тоже управлялось мышкой.

Итак, у нас тут есть цель target, вокруг которой будем крутить камеру. Чувствительность мышки, регулируется переменной - sensitivity. И конечно же, предусмотрено смещение offset, на старте, нужно установить позицию таргета и добавить смещение. По поводу, limit, это ограничение по оси Y, если значение будет больше 90, то картинка начнет глючить, поэтому присутствует страховка. Вешаем скрипт на камеру, указываем объект + смещение и собственно смотрим, что получилось.

Если нам нужно вращать объект мышкой, то сделаем упрощенный вариант этого скрипта.

Окно сцены имеет несколько способов навигации для ускорения работы.

Содержание

Перемещение стрелками

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

Фокусирование

Если Вы выберете объект в Иерархии и нажмете клавишу F,- вид будет перемещен для центрирования выбранного объекта. Эта функция называется "рамка выбора".

Перемещение, Вращение и Зум

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

Использование инструмента Рука

Когда выбран инструмент Рука (быстрая клавиша Q), доступны следующее управление мышью:

Перемещение: щелчок-перетаскивание для перемещения сцены вокруг камеры.

Вращение: удерживайте Alt и сделайте щелчок-перетаскивание для перемещения камеры вокруг текущей точки опоры.

Масштабирование: удерживайте Control (Command на Mac) щелчок-перетаскивание для масштабирования сцены.Удерживание Shift будет увеличивать скорость перемещений и масштабирования.

Быстрые клавиши без использования инструмента Рука

Для большей эффективности все эти способы могут быть использованы не зависимо от того какой инструмент трансформации выбран. Удобство управления зависит от того что Вы используете - мышь или трекбол:

Удерживаем Alt-Command и щелкнув тащим.

Режим пролета

Режим пролета позволяет Вам перемещаться в сцене летая в ней от первого лица подобно тому как это сделано во многих играх.

  • Щелкните и удерживайте правую кнопку мыши.
  • Теперь Вы можете двигаться используя мышь и клавиши WASD для перемещения налево/направо вперед/назад и клавиши Q и E для смещения вверх/вниз.
  • При удерживании Shift Вы будете двигаться быстрее.

Режим пролета разработан для вида перспективы. В виде Изометрии вместо режима пролета будет производиться вращение камеры.

Гизмо сцены

В верхнем правом углу Окна сцены выводится Гизмо сцены. Он отображает текущую ориентацию камеры и позволяет Вам быстро модифицировать угол обзора.

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

В первой части этой серии вы сможете реализовать свою собственную систему 2D веревок для перемещения и узнать о следующем:

  • Создадите систему прицеливания.
  • Использование линейного рендеринга и объединения дистанций для создания веревки.
  • Веревка может обертываться вокруг объектов в игре.
  • Расчет угла вращения веревки и придания силы в этом направлении.

Начало работы с Unity

Скачайте стартовый проект для этого учебника и откройте его в редакторе Unity. Убедитесь, что вы используете Unity 2017.1 или новее.

Откройте сцену Game, расположенную в папке Scenes и взгляните на то, с чем вы скоро начнете работать:

a 2D Grappling Hooks Game

У нас есть основной персонаж (слизняк) и скалы.

Значимыми компонентами являются игровой объект Player, который имеет капсульный коллайдер и rigidbody (жесткое тело), которые позволяют ему взаимодействовать с физическими объектами. Также у нам есть простой скрипт для перемещения (PlayerMovement), который позволяет нашему скользкому персонажу ползать по земле и прыгать.

Нажмите на кнопку Play в редакторе, чтобы начать игру и испытать элементы управления. Клавиши A и D позволяют нам перемещаться влево и вправо, а клавиша "пробел" - выполнять прыжки. Будьте осторожны, чтобы не проскользнуть и не упасть с камней, иначе вы умрете!

Не убейте вашего Unity-персонажа

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

Создание крючков и веревок

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

  • Line Renderer, который покажет веревку. Когда веревка обертывает предметы, вы можете добавить больше сегментов в рендеринг линии и правильно расположить вершины по краям изгибающейся веревки.
  • DistanceJoint2D. Может использоваться для придания веревке конкретной точки захвата и для того, чтобы наш персонаж на ней качался. Это также позволит настроить расстояние, которое можно использовать для спуска вверх и вниз по канату.
  • Игровой объект с RigidBody2D, который может быть перемещен в зависимости от текущего местоположения точки привязки крючка. Это будет, по сути, шарнирная петля / опорная точка.
  • Рейкаст для метания крюка и прикрепления к объектам.

Выберите Player в Иерархии и добавьте новый Игровой объект в Player по имени RopeHingeAnchor. Этот Игровой объект будет использоваться, чтобы расположить шарнир / опорную точку крюка для захвата, где бы этот крюк ни находился во время игры.

Добавьте компоненты SpriteRenderer и RigidBody2D в RopeHingeAnchor.

В SpriteRenderer установите свойство Sprite в UISprite и измените Order in Layer на 2 . Отключите компонент unchecking, сняв флажок рядом с его именем.

В компоненте RigidBody2D установите свойство Body Type равным Kinematic . Эта точка будет вращаться не за счет физического движка, а благодаря коду.

Задайте Layer значение Rope и установите значения Scale по осям X и Y равными 4 в компоненте Transform.


Выберите Player снова и добавьте новый компонент DistanceJoint2D.

Захватите и перетащите RopeHingeAnchor на Иерархии в свойство Connected Rigid Body компонента DistanceJoint2D и отключите Auto Configure Distance.

Удалите метод Update. В верхней части скрипта, внутри объявления класса RopeSystem, добавьте следующие переменные, а также методы Awake и Update:

Поясним, что здесь происходит:

  1. Эти переменные мы станем использовать для отслеживания различных компонентов, с которыми будет взаимодействовать скрипт RopeSystem.
  2. Метод Awake будет запущен когда игра начнется и отключит ropeJoint (компонент DistanceJoint2D). Он также установит playerPosition на текущую позицию Игрока.
  3. Это самая важная часть вашего основного цикла Update(). Во-первых, вы фиксируете положение курсора мыши в игровом мире, используя метод ScreenToWorldPoint . Затем вы вычисляете направление движения, вычитая позицию игрока из позиции мыши. Зная его, мы можем вычислить aimAngle, который представляет собой угол наклона курсора мыши. Значение корректируется с помощью условного оператора if.
  4. aimDirection - это вращение. Нас интересует только значение Z, поскольку вы используете 2D-камеру. Мы используем Mathf.Rad2Deg для преобразования угла из радиан в градусы.
  5. Позиция игрока отслеживается с помощью удобной переменной, которая позволяет вам не ссылаться все время на transform.Position .
  6. Наконец, условие if..else , которое использовать, чтобы определить крепится ли веревка к опорной точке.

Сохраните скрипт и вернитесь в редактор.

Прикрепите компонент RopeSystem к Игроку и подключите различные компоненты к публичным полям, которые вы создали в скрипте RopeSystem. Перетащите Player, Crosshair и RopeHingeAnchor в соответствующие поля:

  • Rope Hinge Anchor: RopeHingeAnchor
  • Rope Joint: Player
  • Crosshair: Crosshair
  • Crosshair Sprite: Crosshair
  • Player Movement: Player

Забавно: мы возимся над вычислениями для прицеливания, но нет никаких визуальных маркеров, чтобы показать результаты нашей работы. Давайте исправим это.

Откройте скрипт RopeSystem и добавьте к нему новый метод:

Этот метод будет определять перекрестье, основанное на aimAngle , который вы проходите (и значение которого вы рассчитали в Update() ) таким образом, что вокруг вас он делает круг, радиус которого равен 1 единице. Это также включит спрайт перекрестия, если даже до этого мы этого не делали.

В Update() измените условие, которое проверяет !ropeAttached :

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

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

Добавьте следующие переменные после имеющихся в скрипт RopeSystem:

The LineRenderer хранит ссылку на линейный рендеринг, который отображает веревку. LayerMask позволяет вам самостоятельно определить, с какими физическими слоями рейкаст сможет работать. Значение ropeMaxCastDistance устанавливает максимальную дистанцию рейкаста.

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

Добавьте следующие новые методы:

Вот объяснение того, что делает приведенный выше код:

  1. HandleInput вызывается из цикла Update() и ожидает клик мышкой.
  2. При левом клике включается линейный рендеринг веревки, а 2D-рейкаст выстреливается от игрока в направлении прицела. Максимальное расстояние задается таким, что веревку нельзя выстрелить на бесконечно длинное расстояние, а еще появляется специальный маркер, позволяющий определить, какие слои рейкаст может задеть, а какие нет.
  3. Если рейкаст что-либо задевает, ropeAttached устанавливается в true и идет проверка списка верхних позиций веревки, чтобы убедиться, что задетая точка не имеет максимальное значение.
  4. 4. Если значение из предыдущего пункта устанавливается в true, игровому персонажу придается небольшой импульс, который заставляет его подпрыгивать, а ropeJoint (DistanceJoint2D) включается и создает дистанцию, равную между персонажем и точкой присоединения. Также включается спрайт этого самого присоединения.
  5. Если рейкаст ничего не задевает, то линейный рендеринг и присоединение веревки отключены, а значение ropeAttached устанавливается в false .
  6. Если щелкнуть правой кнопкой мыши, то вызовется метод ResetRope() , который отключит и сбросит все параметры веревок и крюков на такие, как если бы они не использовались.

В самом низу метода Update добавьте вызов нового метода HandleInput() и передайте в него значение aimDirection :

Сохраните ваши изменения в RopeSystem.cs и вернитесь обратно в ваш редактор.

Добавление веревки

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

Линейный рендеринг идеально для этого подходит, т.к. он позволяет создавать вам необходимое количество точек и их позиций в пространстве игрового мира.

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

Выберите Player и добавьте к нему компонент LineRenderer component to it. Задайте Width равным 0.075 . Разверните Materials и для Element 0, выберите материал RopeMaterial из папки Materials. Наконец, для Line Renderer (Линейного рендеринга) выберите Distribute Per Segment напротив пункта Texture Mode.


Перетащите компонент Line Renderer в Rope System поля Rope Renderer.

Кликните на раскрывающемся списке Rope Layer Mask и выберите Default, Rope, and Pivot в качестве слоев, с которыми может взаимодействовать рейкаст. Это гарантирует, что когда рейкаст будет создан, он будет сталкиваться только с этими слоями, а не с другими вещами, такими как игрок.

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

Дистанция соединения не задана, а значит, что и вершины линейного рендеринга тоже не настроены. Таким образом, получается, что веревку мы не видим из-за того, что максимальная дистанция ее выстрела находится прямо на голове нашего персонажа, и это значение сталкивает его вниз на камни.

Не волнуйтесь, сейчас мы с этим разберемся.

В скрипте RopeSystem.cs добавьте новый оператор using в начало класса:

Это позволяет использовать LINQ-запросы, которые позволят вам легко найти первый или последний элемент в списке ropePositions.

Добавьте под имеющимися переменными новую переменную по имени distanceSet логического типа:

Вы будете использовать ее как флаг, чтобы дать скрипту понять, что дистанция веревки (для той точки между игроком и текущим поворотом, в которой установлен "крюк") установлена правильно.

Теперь добавьте новый метод, который вы будете использовать для настройки верхних позиций веревки на линейном рендеринге и настройки дистанции. Он основан на имеющемся списке позиций веревки, с которым мы будем работать ( ropePositions ):

Поясним этот код:

  1. Выходим из этого метода, если веревка на самом деле не присоединилась.
  2. Задаем счет вершин линейного рендеринга веревки (позиций) до числа позиций, хранящегося в ropePositions , плюс еще 1 (для позиции игрока).
  3. Прокручиваем назад по списку ropePositions и для каждой позиции (кроме последней), устанавливаем позицию вершины линейного рендеринга как Vector2 которая хранится в ropePositions .
  4. Устанавливаем позицию крюка на предпоследнюю позицию, где он должен быть; либо, если у нас есть только одна позиция, устанавливаем ее. Это задает дистанцию ropeJoint ropeJoint как дистанцию между игроком и текущей позицией веревки.
  5. Оператор if обрабатывает случай, когда позиция веревки является предпоследней; то есть точку, когда веревка присоединяется к объекту, являющемуся текущей точкой присоединения.
  6. Блок else обрабатывает настройки последней позиции вершины веревки и текущей позиции игрового персонажа.

Добавьте вызов UpdateRopePositions(); внизу Update() , сохраните изменения в скрипте и снова запустите игру. Сделайте небольшой прыжок с помощью клавиши 'пробел', прицельтесь и выстрелите по скале над вами. Теперь вы можете полюбоваться плодами своего труда, смотря как червяк болтается над скалами.

Теперь, я предлагаю, сделать перерыв и продолжить изучение во второй части веревочного урока по Unity.

Читайте также: