Перейти к содержимому

Как сделать телепорт в юнити 3д

  • автор:

Телепортация игрока в Unity с OpenXR

Продолжим серию статей про OpenXR. В конце концов получим контроллер игрока, обладающий базовыми навыками — перемещением, поворотом и взаимодействием с объектами. Взаимодействие с объектами мы рассмотрим в следующей статье. В этой же мы сделаем телепортацию игрока и его поворот.

Для работы над текущей задачей мы возьмем проект из предыдущего урока за основу, удалив из него скрипт HandCapsule. Это был демонстрационный скрипт, показывающий нам как работать с API OpenXR из Unity, и более он нам не потребуется — мы будем писать уже «по-настоящему».

Перед тем как начать, давайте отделим неподконтрольную нам часть от подконтрольной. Создадим дочерний для XR Rig объект Player Avatar, а в нём создадим объекты Left Hand и Right Hand. Рукам-капсулам мы зададим scale (0.05, 0.05, 0.05). В руках мы создадим объект Pointer и разместим его на «макушке» наших капсул и повернем его таким образом, чтобы forward Pointer’а смотрел наверх. Значения трансформа Pointer’а: поворот по x -90, координаты (0, 1, 0).

Hand

Создадим класс Hand — основной скрипт для всех работы с инпутом контроллеров и взаимодействия с виртуальным миром. В начале класса мы объявим поля TargetTransform , чтобы понимать, какое местоположение сейчас у «настоящего» контроллера, InputDeviceManager из прошлой статьи, чтобы взаимодействовать с инпутом, и флаг IsLeftHand, чтобы понимать, какой InputDevice нам брать для обработки инпутов. Также, заведем свойство InputDevice , возвращающее конкретный для данной руки InputDevice из InputDeviceManager .

 public Transform TargetTransform; public InputDeviceManager InputDeviceManager; public bool IsLeftHand; public InputDevice InputDevice => IsLeftHand ? InputDeviceManager.LeftController : InputDeviceManager.RightController;

Данный скрипт навесим на оба объекта рук: Left Hand и Right Hand, и проставим им все необходимые ссылки, а флаг IsLeftHand выставим в true для Left Hand.

Компонент Hand для левой руки

Перед началом работы с инпутом, необходимо повторить функционал из предыдущего урока: перемещение капсул за руками. В прошлом уроке мы просто повесили капсулы на Tracked Pose, сейчас же объекты капсул существуют без какой-либо логики перемещения в пространстве. Напишем её, благо она очень простая: просто будем повторять в LateUpdate положение и вращение соответствующей Tracked Pose.

private void LateUpdate()

Hand будет выполнять на данном этапе роль обработчика событий с инпута соответствующего ему контроллера, потому давайте заведем четыре события, необходимые нам для реализации телепортации игрока и его поворота: TeleportPressed, TeleportReleased, TurnLeft и TurnRight. Делегат для них будем использовать void HandInteraction(Hand hand) — его я положил в отдельный файл, но в скрипте приведу рядом с событями.

public delegate void HandInteraction(Hand hand); public event HandInteraction TeleportPressed; public event HandInteraction TeleportReleased; public event HandInteraction TurnLeft; public event HandInteraction TurnRight;

Немного о событиях:

  • TeleportPressed будем вызывать тогда, когда стик только отклонился вперёд.
  • TeleportReleased будем вызывать тогда, когда стик перешел из состояния «отклонен вперед» в нейтральное.
  • TurnLeft и TurnRight будем вызывать тогда, когда стик отклонился влево или вправо соответственно.

Реализуем обработку данных событий:

private void Update() < ProcessThumbstick(); >private void ProcessThumbstick() < _prevThumbstickAxis = _thumbstickAxis; InputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out _thumbstickAxis); const float teleportThreshold = 0.66f; if (_prevThumbstickAxis.y < teleportThreshold && _thumbstickAxis.y >= teleportThreshold) < TeleportPressed?.Invoke(this); >else if (_prevThumbstickAxis.y >= teleportThreshold && _thumbstickAxis.y < teleportThreshold) < TeleportReleased?.Invoke(this); >const float turnThreshold = 0.66f; if (_prevThumbstickAxis.x < turnThreshold && _thumbstickAxis.x >= turnThreshold) < TurnRight?.Invoke(this); >else if (_prevThumbstickAxis.x >= -turnThreshold && _thumbstickAxis.x < -turnThreshold) < TurnLeft?.Invoke(this); >>

Теперь наша рука перемещается вслед за контроллерами, а также выстреливает событиями на отклонение стика вперед и влево/вправо. Преступим к реализации самой логики.

Игрок

Реализуем два простых метода на перемещение игрока и его поворот. Создадим класс Player и опишем методы для работы с Transform XR Rig’а:

public class Player : MonoBehaviour < public void SetPosition(Vector3 position) < transform.position = position; >public void Rotate(float angle) < transform.Rotate(0, angle, 0); >>

Сам компонент навешиваем на объект XR Rig. Вызов метод SetPosition переместит игрока в указанные координаты, а метод Rotate будет отвечать за поворачивание игрока по оси Y (в горизонтальной плоскости).

Телепортация

Реализация телепортации состоит из двух скриптов: Teleport.cs, реализующий логику телепортации и который мы напишем сами, и Arc.cs, занимающийся отрисовкой арки телепортации и который мы возьмем с gist.github.com Скрипт рисования арки является косметическим и вместо него можно было бы использовать простой LineRenderer, но я выбираю красивое и готовое решение для концентрации на логике работы с OpenXR.

Перейдем к самой логике телепорта.

Создадим новый Mono Behaviour и называем его Teleport. В нём вводим несколько публичных полей: ссылку на игрока, ссылку на руку для подписки на события стика, ссылка на арку для управления её отрисовкой, ссылка на точку, из которой будет рисоваться арка, и скорость луча (влияет на его дистанцию).

public Player Player; public Hand Hand; public Arc Arc; public Transform Source; public float TeleportVelocity = 10f;

Также, введём несколько приватных переменных: _arcEnabled для оптимизации работы с просчётом луча, _arcIsValid для присваивания результата просчёта луча и _lastArcTargetPosition для хранения последних координат, куда утыкался луч телепорта.

private bool _arcEnabled; private bool _arcIsValid; private RaycastHit _lastArcTargetPosition;

Далее, подпишемся на события Hand.TeleportPressed и Hand.TeleportReleased и напишем логику для них. На отведение стика мы будем включать луч и начинать его отрисовывать, а как только стик будет возвращаться в своё исходное положение, мы будем выключать отрисовку луча и телепортировать игрока в конечные координаты, если телепортировать туда было возможным.

private void OnEnable() < Hand.TeleportPressed += StartTeleport; Hand.TeleportReleased += FinishTeleport; >private void OnDisable() < Hand.TeleportPressed -= StartTeleport; Hand.TeleportReleased -= FinishTeleport; >private void StartTeleport(Hand hand) < _arcEnabled = true; Arc.Show(); >private void FinishTeleport(Hand hand) < _arcEnabled = false; if (_arcIsValid && Arc.IsArcValid()) < Player.SetPosition(_lastArcTargetPosition.point); >Arc.Hide(); >

Также напишем логику рисования луча. Скрипт отрисовки арки требует для отрисовки передачи каждый кадр местоположения, вращения и других параметров работы луча (SetArcData) и вызова самого метода отрисовки (DrawArc). Будем вызывать их в Update.

private void Update() < if (_arcEnabled) < Arc.SetArcData(Source.position, TeleportVelocity * Source.forward, true, false, false); _arcIsValid = Arc.DrawArc(out _lastArcTargetPosition); >>

Навесим оба скрипта (Arc и Teleport) на объекты Left Hand и Right Hand и настроим их.

Пример настройки компонентов Arc и Teleport на примере левой руки. Материал для телепорта можно использовать стандартный.

Поворот игрока

Создадим класс TurnPlayer — класс, ответственный за поворот игрока при отклонении стика влево и вправо.

Объявим необходимые поля для работы скрипта: ссылка на игрока, ссылка на руку и угол поворота игрока при отклонении стика.

public Player Player; public Hand Hand; public float Angle = 45f;

И опишем методы подписки на события Hand.TurnLeft и Hand.TurnRight, поворачивающие игрока на указанное в поле Angle значении:

private void OnEnable() < Hand.TurnLeft += TurnLeft; Hand.TurnRight += TurnRight; >private void OnDisable() < Hand.TurnLeft -= TurnLeft; Hand.TurnRight -= TurnRight; >public void TurnLeft(Hand hand) < Player.Rotate(-Angle); >public void TurnRight(Hand hand)

Компонент TurnPlayer навешиваем на каждую руку (Left Hand и Right Hand) и настраиваем.

Компонент TurnPlayer на примере левой руки.

Ну и в конце концов, создадим тег TeleportArea и повесим его на нашу плоскость. Этот тег позволит нам разделять в дальнейшем области, доступные для телепортации и недоступные для неё.

В итоге у нас должна получиться механика, благодаря которой мы можем более менее удобно перемещаться по нашей сцене. Протестируем её: запускаем Play Mode и отклоняем стик вперёд — луч телепорта начинает рисоваться красным, если телепортироваться в указанную область нельзя, и зеленым, если перемещение возможно. На отклонение стика влево и вправо мы будем поворачиваться в соответствующую сторону.

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

Скоро в OTUS состоится бесплатное открытое занятие «AR сегодня: в развлечениях, в образовании, на работе». На нем узнаете, как AR технологии проникли во все сферы вашей жизни, и попробуете сами создать AR мини-игру. Регистрируйтесь по ссылке.

как сделать телепорт объекта

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

 public class небо : MonoBehaviour < public Vector2 direction; public float speed = 2; void FixedUpdate() < transform.Translate(direction.normalized * speed); >> 

Отслеживать
user302909
задан 1 авг 2020 в 19:50
Dark Lord Tehnology Dark Lord Tehnology
35 6 6 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Вы же правильно пишите, что для зацикливания нужно просто когда облако уйдет направо за экран перемещать его в левую часть экрана (точнее в левую часть за экраном, чтобы оно потихоньку выплыло). Что именно вам не понятно? Как это реализовать? Если да, то реализовать это можно с помощью условия если облако ушло за экран, то переместиться в левую часть экрана:

if (transform.position.x > Screen.width)

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

Гайды по Unity

Как правильно разрезать изображения на спрайты в Unity

Как найти объект по имени и тегу в Unity

Создание простого таймера в Unity

Как подключить рекламу в Unity Ads

Как настроить билд WebGL и загрузить игру в Яндекс Игры

Создание костной 2д анимации в Unity

Сохранение данных с помощью PlayerPrefs

Основы создания партиклов в Unity

Как получить доступ к переменной другого скрипта

Подключаем Yandex рекламу для Яндекс Игр на Unity

Поворот 2д персонажа в сторону его движения

2д стрельба в сторону курсора мыши на Unity

Проверка наличия земли под ногами персонажа перед прыжком

Создание игрового меню

Реализация Стрельбы

Создание полосы здоровья

Создаём простой инвентарь в Unity

Как определить позицию курсора мыши в Unity

Преследование вражеского персонажа за игроком

Как создать магазин ресурсов и предметов

Прыжок Персонажа

Создание простых диалогов

Как подключить внутриигровые покупки для Яндекс Игр

Способы изменения силы гравитации в Unity

Создаем простой телепорт в Unity

Работа с UI элементами в Unity

Создаём рандомный спавн объектов

Добавление звуков ходьбы в Unity

Подбор монет

Как сделать фоновую музыку в Unity

Создаём тайлмап и палитру тайлов

Персонаж 16
Интерфес 11
Анимация 3
Шаблоны Игр 2
Монетизация 5
Мультиплеер и Сеть 0
Сервисы & API & SDK 1
Виртуальная Реальность 0

Мы запускаем сбор на оплату сервера на Январь месяц, который необходим для работы сайта UnityHub.ru.

Мы нуждаемся в Вашей поддержке.

Телепортация Unity 3D

Мне нежно чтобы телепортация происходила только, если на этих координатах не будет препятствия (Стены).

Что нужно добавить для этого?

Дополнен 4 года назад
Какой скрипт нужно использовать чтобы проверить: телепортируется в коллайдер или нет?
Лучший ответ

создать там коллайдер сферу или куб, если не столкнулись ни с чем (или чем-то с тегом) то телепортировать

Владислав КапраловМастер (1980) 4 года назад

Какой скрипт нужно использовать чтобы проверить: телепортируется в коллайдер или нет?
Просто я недавно начал изучать программирование

Сергей Шиманский Мудрец (11183) использовать функцию OnTriggerEnter или OnTriggerStay или что то вроде того, весь скрипт все равно писать не буду)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *