InDepth - это серия статей о создании атомарных компонентов игры в Unity. Каждую неделю я глубоко погружаюсь в один из аспектов игрового дизайна, будь то Прыжки, Движение или на сегодняшний день: Интерактивные элементы. В одной из статей этой серии рассматриваются аспекты игрового дизайна. каждого компонента, а также обсуждение их реализации. Кроме того, цель должна состоять в том, чтобы эти компоненты оставались модульными, настраиваемыми и масштабируемыми, поскольку я хочу, чтобы они функционировали как базовые строительные блоки моих собственных будущих проектов!

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

TL; DR;

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

  • Создайте два триггера, регистрируя, находится ли игрок рядом (для подачи сигналов или кадрирования) и находится ли игрок в пределах диапазона взаимодействия. События одного триггера должны передаваться из дочернего компонента.
  • Выставьте эти события в инспекторе с помощью UnityEvents. Это позволяет произвольному количеству игровых объектов иметь функции, которые запускаются всякий раз, когда выполняются эти триггерные условия.
  • Используйте перечисления и переключатель, чтобы изменить поведение в зависимости от метода активации, то есть нажатие, отпускание, удержание, ожидание.
  • Создайте префаб для легкого дублирования и абстрагирования сложности.

Код для компонента Interactbles относительно прост, так как большинство функций необходимо будет реализовать где-то еще. В основном он обертывает шаблонный код. Тем не менее, нам очень полезно подумать о дизайне и убедиться, что он правильно масштабируется, когда наши игры становятся большими!

Разработка хорошо сделанных интерактивных элементов

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

Разработка взаимодействия

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

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

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

Далее нам нужно определиться со способом взаимодействия. Мы будем уделять особое внимание взаимодействию с одним ключом. Они, как правило, привязаны к мировому пространству персонажа, то есть взаимодействие происходит там, где персонаж в настоящее время проживает. Обратите внимание, что существует множество других форм, например щелчки мышью, перетаскивание, касание, датчики тела или камеры, не говоря уже о виртуальной реальности. Но давайте будем простыми.

Эта статья Давиде Аверса подробно описывает состояния ввода одной кнопки, то есть нажатие, отпускание, удержание, ожидание (ничего не делает), ритм. Хотя я рекомендую вам прочитать статью самостоятельно, вот основные выводы в сочетании с моими собственными наблюдениями:

  • Нажат. Быстро и прямо. Чувство нейтрального игрока. Подходит для действий, которые происходят часто, требуют быстрого выполнения или полагаются на рефлексы.
  • Выпущено. Имитирует высвобождение напряжения / силы. Если игроку нужно принять очень важное или эмоциональное решение, вы можете поэкспериментировать с запечатыванием действия, только когда отпущена клавиша. Также обратите внимание, что время реакции на отпускание клавиши меньше, чем на нажатие. Конечно, для этого требуется, чтобы пользователь уже держал ключ.
  • Удерживать. Подходит для действий, которые воспринимаются как требующие постоянных усилий, например, раскачивание каната, толкание / натягивание препятствий, ускорение автомобиля и т. Д. Также дает нам возможность создавать диапазоны недвоичных значений при нажатии кнопки в противном случае двоичной.
  • Простой. Этой категории может быть присвоен автоматический сбор предметов в ролевой игре или движение вперед в бесконечном раннере. Подходит для действий, которые происходят часто или несущественны для игрока.
  • Ритм. Относится к повторному нажатию кнопки. Быстрый ритм - это способ приложить физическое усилие к игроку. Используется в таких ситуациях, как когда персонаж открывает тяжелую дверь, и игрок должен нажать кнопку. Другой более медленный ритм можно использовать в таких ситуациях, как ковка или другие точные действия. См. Статью Давиде Аверса для получения дополнительной информации.

Общение взаимодействия

Как упоминалось в предыдущем разделе, игрок должен 1) знать, что взаимодействие существует, и 2) знать, как его выполнить. Давайте посмотрим на три уровня, на которых эта информация хранится или представлена.

  • Знания, условности и последовательность. Как геймеры, мы привыкли видеть вещи определенным образом. Вещи, которые светятся, движутся или иным образом выделяются, скорее всего, будут восприниматься как взаимодействующие, а также привлекающие внимание игроков. Мы можем использовать условные обозначения, такие как использование клавиши E для взаимодействия, и / или научить игрока тому, как взаимодействия работают во время игры. Также может быть полезно придерживаться узнаваемого общего взгляда на интерактивные объекты.
  • Недиегетические элементы. На самом деле не знал, какое слово использовать для этого, но по сути все, что не является частью игрового мира. Это включает, например, Всплывающие окна пользовательского интерфейса, озвучка, джинглы, звук, работа камеры и кадрирование. Все это есть собственные темы, но рассмотрим, например, камеру, которая кадрирует важные элементы, если игрок находится рядом (см. Пример), или иконический звук, который воспроизводится каждый раз, когда на экране появляется новый интерактивный объект!
  • Элементы игрового мира. Это могут быть указатели в игре, персонаж, который смотрит в направлении взаимодействующих объектов, огни, которые тактически размещены для привлечения внимания, или звуковые сигналы от персонажи, дающие игроку понять, что что-то рядом. В качестве побочного примечания рекомендуется полагаться на звуковые сигналы, чтобы убедиться, что есть множество визуальных сигналов, дополняющих их, поскольку не все геймеры предпочитают вкладывать очки в способность слышать!

Мы могли бы упомянуть здесь ТАКОЕ МНОГОЕ, но все эти вещи, как мы обсуждали ранее, не являются частью самого интерактивного объекта. Нам просто нужно знать о них и упростить для нас привязку их к интерактивному объекту позже.

Реализация

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

Помните, что мы хотим поддерживать как 1) сообщение о том, что интерактивный объект находится относительно близко, 2) что игрок находится в диапазоне, в котором может происходить взаимодействие, и 3) что игрок совершил взаимодействие. Также может быть полезно узнать, покинул ли игрок эти зоны! Вы можете назвать их как хотите, но мы должны показать что-то вроде следующих событий:

  • onInteract. Игрок совершил взаимодействие.
  • onInteractableEnter. Игрок находится в пределах досягаемости, чтобы начать взаимодействие.
  • onInteractableExit. Игрок покинул зону, в которой он может взаимодействовать.
  • onNotifyingEnter. Игрок находится достаточно близко, поэтому вы можете предложить ему, что взаимодействие находится поблизости.
  • onNotifyingExit. Игрок снова покинул этот диапазон.

Затем введите: UnityEvents. Эти вещи действительно мощные. Вы определяете и используете их так:

[SerializeField] private UnityEvent onNotifyingEnter;
//...
onNotifyingEnter.Invoke();

При этом нам разрешено создавать список функций, которые запускаются каждый раз при вызове onNotifyingEnter.Invoke (). Предположим, мы хотим отодвинуть камеру подальше, когда игрок приближается к интерактивному объекту. Для этого создайте функцию с поведением уменьшения масштаба в скрипте на камере. Перетащите камеру в UnityEvent onNotifyingEnter. Возможно, сделайте то же самое для сброса масштабирования. Это могло бы выглядеть так:

Мы можем зарегистрировать, если игрок переместился в соответствующие диапазоны, используя два коллайдера, настроенных для срабатывания. Теперь Unity не является большим поклонником наличия нескольких коллайдеров на одном GameObject. По этой причине нам действительно нужно разместить один из триггеров на дочернем объекте и использовать сценарий, чтобы передать события триггера родительскому объекту:

Последнее, что нужно сделать - это создать реальное взаимодействие. Помните наше обсуждение состояний ввода кнопок? Мы можем смоделировать его с помощью перечисления таким образом (он создаст раскрывающийся список в инспекторе):

private enum activationMode {press, release, hold, idle};
[SerializeField] private activationMode mode = activationMode.press;

Затем, в зависимости от того, какое значение установлено для mode, мы можем обрабатывать ввод по-разному. Я использовал оператор switch в своей собственной реализации. Работает это так:

  • В случае, если это режим idle, onInteract вызывается один раз, когда игрок входит в диапазон взаимодействия.
  • Если установлен режим нажать или отпустить, я использую дополнительную проверку для Input.GetKeyDown (клавиша) и Input.GetKeyUp (клавиша) соответственно.
  • Наконец, hold настроен на непрерывный вызов, пока клавиша удерживается с помощью Input.GetKey (key).

Несколько последних заметок

Вы можете заметить, что я решил не использовать ритм. Я считаю его продолжением либо press, либо release. Таким образом, он не реализуется непосредственно в интерактивном элементе.

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

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

Надеюсь, это может вас заинтересовать. Ваше здоровье!