Использование карт действий для назначения кнопок игровому поведению

Страница обновлена :
Дата создания страницы :

Среда верификации

Виндоус
  • Windows 11
Редактор Unity
  • 2020.3.25f1
Входной системный пакет
  • 1.2.0

Предпосылки для этого совета

Следующие настройки были сделаны заранее в качестве предпосылки для описания этого совета.

О картах действий

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

Создание карты действий

Здесь я хотел бы создать карту действий и отобразить вводимую пользователем информацию в тексте. Существует несколько способов получения пользовательского ввода с помощью Action Maps.

Щелкните правой кнопкой мыши любую папку в проекте, чтобы создать действие ввода. Расположение создаваемой папки произвольно, но, пожалуйста, управляйте ею в соответствии с вашим проектом. Имя файла также произвольное, но здесь InputActionSample оно .

При двойном щелчке по созданному файлу отобразится следующее окно.

Сначала нажмите кнопку + в Action Maps, чтобы создать карту действий. Как единица создания, если содержание операции изменяется в зависимости от сцены, оно будет определено в этом блоке. Например, в случае экшена с боковой прокруткой содержимое операции меняется во время действия и в меню, поэтому вы создадите карту действий для каждой.

Здесь, в качестве примера, мы определяем действие боковой прокрутки и называем его «SideScrollActionMap».

Затем создайте Действия. Поскольку это образец, я не буду делать их много, но здесь мы создадим действия «Перемещение» для передвижения и «Атака» для атаки. Поскольку он уже создан, измените имя или создайте новое, нажмите кнопку + в правом верхнем углу и введите его.

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

Когда вы выбираете «Переместить», справа есть выбор «Тип действия», поэтому установите для него значение «Значение».

Ниже вы увидите тип элемента управления, поэтому выберите Vector2. Это связано с тем, что верх и низ отнесены к Y, а левое и правое — к X.

Затем выберите ключ, который вы хотите назначить этому событию. Выберите «Без привязки» посередине и выберите «Путь» справа. Здесь мы выбираем GamePad LeftStick.

Это привязывает левый джойстик GamePad к движению.

Чтобы привязать и другие контроллеры, выберите «Добавить привязку» на кнопке + справа от «Переместить».

Теперь, когда добавлен параметр «Без привязки», мы назначаем Dpad для GamePad.

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

Джойстики и Dpad — это кнопки, которые предполагают вверх, вниз, влево и вправо, поэтому их можно добавлять вместе с этим, но в случае клавиатур все они являются отдельными клавишами, поэтому нет определения для вверх, вниз, влево и вправо. Чтобы настроить клавиатуру вверх, вниз, влево или вправо, выберите «Добавить вверх, вниз, влево, вправо» на кнопке +.

Затем будет добавлен 2D-вектор, и вы можете назначить его каждому Вверх, Вниз, Влево, Вправо, как показано на рисунке ниже.

Например, если вы используете кнопку «Вверх», установите «Стрелку вверх» на клавиатуре. Кстати, если вам сложно найти ключ, вы можете легко выбрать его, нажав целевую клавишу при нажатии кнопки «Прослушать».

Теперь для параметра «Вверх» установлено значение «Стрелка вверх».

Точно так же установите «Вниз», «Влево» и «Вправо», и все готово.

Конечно, можно установить не только клавиши курсора, но и WASD.

Далее настройте Attack. Атаку легко назначить, потому что это одна кнопка. Сначала выберите «Атака» и убедитесь, что «Тип действия» — это кнопка.

Затем выберите «Без привязки» и выберите кнопку, которую вы хотите назначить, в пути.

Если вы хотите добавить больше, выберите «Добавить привязку» с помощью кнопки +.

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

Когда все настройки будут завершены, нажмите «Сохранить актив» для сохранения. Вы можете закрыть это окно.

Наконец, с помощью файла inputactions проекта (в данном случае файла InputActionSample, который вы создали ранее) установите флажок «Создать класс C#» в инспекторе. Параметр будет добавлен, но нажмите кнопку «Применить» как есть.

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

Как получить входную информацию

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

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

Получение входной информации в окне «Отправить сообщения»

Первый способ здесь заключается в том, как получить входную информацию в «Отправить сообщения».

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

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

Затем добавьте компонент Player Input к пустому объекту. Player Input является важным компонентом для соединения карт действий и скриптов.

В «Добавить компонент» в категории «Ввод» есть «Ввод игрока», поэтому добавьте его.

После добавления компонента «Ввод игрока» установите карту действий, созданную в разделе «Действия». Перетащите его из проекта или выберите его с помощью значка + справа.

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

Убедитесь, что выбрано поведение «Отправлять сообщения».

Далее создайте сценарий. Имя файла может быть любым, но вот InputSendMessage оно.

Скрипт выглядит следующим образом:

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputSendMessage : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>
  /// Move アクションが実行されたときに呼ばれる。
  /// </summary>
  /// <param name="inputValue">入力量。</param>
  public void OnMove(InputValue inputValue)
  {
    var vec = inputValue.Get<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Attack アクションが実行されたときに呼ばれる。
  /// </summary>
  public void OnAttack(InputValue inputValue)
  {
    TextObject.text = $"Attack:{inputValue.isPressed}\n{TextObject.text}";
  }
}
  • К объекту прикреплен ввод игрока, который задает параметр «Отправить сообщения»
  • Наследование от MonoBehaviour

Если условия выполнены, то, если вы определите метод с именем «OnXXXXXXXX», Целевой метод будет вызван при выполнении указанной операции действия. "ХХХХХХХХ" - это название Действий, созданных в карте действий. Здесь мы создали действия «Переместить» и «Атаковать», поэтому имена методов — «OnMove» и «OnAttack» соответственно.

OnMove Вы можете получить введенную сумму из аргумента InputValue . Поскольку для параметра «Тип элемента управления» установлено значение «Вектор 2», входное значение InputValue.Get<Vector2> будет получено в формате .

OnAttackInputValue.isPressed Вы также можете узнать, нажимаете ли вы.

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

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

Как вы можете видеть, когда вы перемещаете его, вы можете видеть, что метод вызывается только тогда, когда есть изменение значения по сравнению с предыдущим состоянием. Например, при перемещении стика влево он называется целеустремленно, но не влево (- OnMove 1,0). OnMove Кнопка «Атака» также реагирует только в момент ее нажатия, и если она нажата и удерживается, метод не вызывается.

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

Кстати, в текущем состоянии она не вызывается при отпускании кнопки, поэтому определить, когда OnAttack кнопка отпускается, не представляется возможным. Чтобы отреагировать на это, выберите действие «Атака», определяющее кнопку, в настройках карты действий и добавьте «Нажатие» из «Взаимодействия». После этого установите триггерное поведение добавленного нажатия на «Нажмите и отпустите» и сохраните его.

При выполнении вы можете видеть, что вызывается даже OnAttack тогда, когда кнопка отпущена. isPressed false Поскольку он становится, также можно определить, является ли это временем выпуска.

Кстати, пожалуйста, удалите это взаимодействие, потому что оно не будет использоваться в будущем.

Получайте входные данные с помощью Invoke Unity Events

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

Во-первых, поместите текстовый объект так, чтобы можно было отобразить входную информацию.

Invoke Unity Events создает пустой объект, выполняющий связанные операции.

Добавьте Input > Player Input к пустому объекту.

Задайте файл карты действий, созданный для Actions (в данном случае InputActionSample), и задайте для созданной карты действий (в данном случае SideScrollActionMap) значение Карта по умолчанию. Задайте поведение для вызова событий Unity.

Создайте сценарий. Название произвольное, но в данном случае InputInvokeUnityEvents это .

Скрипт выглядит следующим образом:

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputInvokeUnityEvents : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnMove(InputAction.CallbackContext context)
  {
    var vec = context.ReadValue<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Move 操作を行ったときに呼ばれる。
  /// </summary>
  /// <param name="context">コールバック内容。</param>
  public void OnAttack(InputAction.CallbackContext context)
  {
    var value = context.ReadValueAsButton();
    TextObject.text = $"Attack:{value}\n{TextObject.text}";
  }
}

Имя OnMoveOnAttack метода, которое вызывается при взаимодействии пользователя с ним, — , как в случае с отправкой сообщений. В Invoke Unity Events вы можете задать это имя метода по своему усмотрению.

Когда каждый из них вызывается, он передается в качестве аргументаInputAction.CallbackContext, поэтому вы можете получить статус ввода оттуда. Если вы зададите «значение» в действии, вы можете получить его в методе, а если вы установите ReadValueAsButton «кнопку», вы ReadValue можете получить его в методе.

После сохранения сценария присоедините ввод проигрывателя к задаваемому объекту и задайте отображаемый текстовый объект.

Затем разверните «Событие» и «Имя карты действий (SideScrollActionMap)» во входе игрока, и вы должны увидеть созданные вами действия «Перемещение» и «Атака».

Сначала нажмите кнопку + кнопку «Переместить», чтобы добавить его.

Объект в левом нижнем углу — это ваш собственный объект, а для параметра Function задано значение только что созданного OnMove метода.

Также настройте событие атаки.

Запустите игру, чтобы увидеть, как она работает.

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

Использование автоматически сгенерированного скрипта для получения входной информации

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

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

Поместите текстовый объект для отображения входной информации.

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

Сценарий, автоматически сгенерированный из карты действий, — это просто библиотека, поэтому создайте отдельный сценарий управления. Название произвольное, но в данном случае InputScript это .

Скрипт выглядит следующим образом:

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputScript : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>アクションマップから自動生成されたクラス。</summary>
  private InputActionSample _actionMap;

  private void Awake()
  {
    // 各操作を行ったときに呼ばれるイベントを設定する
    _actionMap = new InputActionSample();
    _actionMap.SideScrollActionMap.Move.performed += context => OnMove(context);
    _actionMap.SideScrollActionMap.Attack.performed += context => OnAttack(context);
  }

  private void OnEnable()
  {
    // このオブジェクトが有効になったときにアクションマップを有効にする
    _actionMap.Enable();
  }

  private void OnDisable()
  {
    // このオブジェクトが無効になったときにアクションマップが余計な動作を起こさないように無効にする
    _actionMap.Disable();
  }

  /// <summary>
  /// Move 操作をした時に呼ばれるメソッドです。
  /// </summary>
  /// <param name="context">コールバックパラメータ。</param>
  public void OnMove(InputAction.CallbackContext context)
  {
    // Move の入力量を取得
    var vec = context.ReadValue<Vector2>();
    TextObject.text = $"Move:({vec.x:f2}, {vec.y:f2})\n{TextObject.text}";
  }

  /// <summary>
  /// Attack 操作をした時に呼ばれるメソッドです。
  /// </summary>
  /// <param name="context">コールバックパラメータ。</param>
  public void OnAttack(InputAction.CallbackContext context)
  {
    // Attack ボタンの状態を取得
    var value = context.ReadValueAsButton();
    TextObject.text = $"Attack:{value}\n{TextObject.text}";
  }
}

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

Awake В методе создается экземпляр и задается событие, InputActionSample вызываемое во время действия. При OnMoveвыполнении этих операций вызывается метод , OnAttack который вызывается.

Однако, поскольку мы устанавливаем здесь только событие, нам OnEnable нужно вызвать метод when Enable , чтобы включить карту действий.

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

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

Запустите игру, чтобы увидеть, как она работает.

Как видите, метод не вызывается, когда OnMove операция Move становится (0, 0). Я не уверен, почему, но кажется, что выполненное событие на самом деле принимает только то, в котором включены нажатия клавиш.

Кстати, если вы не установили Взаимодействия в карте действий для Атаки, она не будет вызываться при OnAttack отпускании кнопки.

Чтобы canceled справиться с этим, вам нужно настроить событие. Если вы не хотите выполнять специальную обработку при (0, 0), вы можете вызвать метод в том виде, в котором он есть OnMove . То же самое верно и для Attack.

private void Awake()
{
  // 各操作を行ったときに呼ばれるイベントを設定する
  _actionMap = new InputActionSample();
  _actionMap.SideScrollActionMap.Move.performed += context => OnMove(context);
  _actionMap.SideScrollActionMap.Attack.performed += context => OnAttack(context);
  _actionMap.SideScrollActionMap.Move.canceled += context => OnMove(context);       // 追加
  _actionMap.SideScrollActionMap.Attack.canceled += context => OnAttack(context);   // 追加
}

Запустите и убедитесь, что отображается Move:(0, 0) или Attack:False.