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

Страницата се актуализира :
Дата на създаване на страница :

Среда за проверка

Уиндоус
  • Прозорци 11
Редактор на единство
  • 2020.3.25ф1
Пакет на входната система
  • 1.2.0

Предпоставки за този съвет

Следните настройки са направени предварително като предпоставка за описанието на този съвет.

За картите с действия

Потребителските програми за въвеждане на клавиатури, мишки и геймпадове основно заявяват, че определено действие се извършва при натискане на бутон. В картата на действията, например, можете да дефинирате действието на "скачане" и да му зададете бутони на контролера и клавиши на клавиатурата. В резултат на това програмата трябва само да опише процеса, когато се извършва конкретно действие. Дори ако зададете бутон на друг контролер като допълнителна мисъл, можете да го приложите, без да променяте операционната програма.

Създаване на карта на действията

Тук бих искал да създам карта на действията и да покажа входната информация на потребителя в текста. Има няколко начина да получите потребителски вход с помощта на карти на действията.

Щракнете с десния бутон върху някоя папка в проекта, за да създадете действие за въвеждане. Местоположението на папката, която ще бъде създадена, е произволно, но моля, управлявайте я според вашия проект. Името на файла също е произволно, но ето InputActionSample го .

Когато щракнете двукратно върху създадения файл, ще се покаже следният прозорец.

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

Тук, като пример, дефинираме действие за странично превъртане и го наричаме "SideScrollActionMap".

След това създайте действия. Тъй като е проба, няма да правя много от тях, но тук ще създадем "Move" действия за движение и "Attack" за атака. Тъй като вече е създаден такъв, моля, променете името или създайте ново, кликнете върху бутона + в горния десен ъгъл и го въведете.

Първо, конфигурирайте конфигурацията за преместване. Контролерът предполага, че използвате клавишите на пръчката, D-pad и курсора на клавиатурата. В случай на действие на странично превъртане, има случаи, в които се използват само ляво и дясно, но тук приемаме, че използвате четири посоки, като обмисляте да скочите с горния клавиш и да приклекнете с клавиша надолу.

Когато изберете Преместване, вдясно има избор на тип действие, така че задайте това на "Стойност".

Ще видите типа на контролата по-долу, така че изберете Vector2. Това е така, защото горната и долната част са присвоени на Y, а лявата и дясната са присвоени на X.

След това изберете ключа, който искате да присвоите на това събитие. Изберете Без обвързване в средата и изберете Път отдясно. Тук избираме GamePad LeftStick.

Това обвързва LeftStick на GamePad с движението.

За да обвържете и други контролери, изберете "Add Binding" от бутона + вдясно от Move.

Сега, когато се добавя No Binding, присвояваме Dpad за GamePad.

По този начин можете да добавите типа контролер, който искате да поддържате, както и ключовете и пръчките. Също така е възможно да го настроите специално за конкретна игрова конзола.

Пръчките и Dpads са бутони, които приемат нагоре, надолу, наляво и надясно, така че те могат да бъдат добавени с това, но в случая с клавиатурите, всички те са единични клавиши, така че няма определение за нагоре, надолу, наляво и надясно. За да настроите клавиатурата нагоре, надолу, наляво или надясно, изберете Добави нагоре надолу ляво дясно композитно от бутона +.

След това ще бъде добавен 2D вектор и можете да го присвоите на всеки нагоре надолу наляво надясно, както е показано на фигурата по-долу.

Например, ако използвате Up, настройте "Стрелка нагоре" на клавиатурата. Между другото, ако ви е трудно да намерите ключ, можете лесно да го изберете, като натиснете целевия клавиш, докато кликнете върху бутона "Слушай".

Нагоре сега е настроен на стрелка нагоре.

По същия начин поставете Надолу, Наляво и Надясно и сте готови.

Разбира се, не само клавишите на курсора, но и WASD могат да бъдат зададени.

След това конфигурирайте Атака. Атаката е лесна за присвояване, защото е един бутон. Първо, изберете Атака и се уверете, че Тип действие е бутон.

След това изберете Без обвързване и изберете бутона, който искате да присвоите от Път.

Ако искате да добавите още, изберете "Добавяне на обвързване" от бутона +.

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

Когато всички настройки са завършени, кликнете върху "Запазване на актива", за да запазите. Можете да затворите този прозорец.

И накрая, с файла за входни действия на проекта (в този случай файлът 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}";
  }
}
  • Обектът има прикачен вход от Media Player, който задава Изпращане на съобщения
  • Наследяване от моноповедение

Ако условията са изпълнени, тогава ако дефинирате метод, наречен "OnXXXXXXXX", Целевият метод ще бъде извикан, когато се извърши зададената операция за действие. "XXXXXXXX" е името на действията, създадени в картата на действието. Тук сме създали действията "Move" и "Attack", така че имената на методите са съответно "OnMove" и "OnAttack".

OnMove Можете да получите въведената сума от аргумента InputValue на . Тъй като типът на контролата е зададен на "Вектор 2", входната стойност InputValue.Get<Vector2> ще бъде получена в .

OnAttackInputValue.isPressed Можете да разберете дали и вие натискате.

След като запишете скрипта, прикачете го към обект, който има компонент Player Input. Задайте и текстовия обект за показване.

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

Както можете да видите, когато го преместите, можете да видите, че методът се извиква само когато има промяна в стойността от предишното състояние. Например, докато движите пръчката наляво, тя се нарича едностранчиво, но не и наляво (- OnMove 1,0). OnMove Бутонът Атака също реагира само в момента, в който е натиснат, а ако е натиснат и задържан, методът не се извиква.

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

Между другото, в текущото състояние не се извиква, когато бутонът се освободи, така че не е възможно да се определи кога OnAttack бутонът се освобождава. За да отговорите на това, изберете действието Атака, което определя бутона в настройките на картата на действията и добавете "Натиснете" от "Взаимодействия". След това задайте поведението на задействане на добавената преса на "Press And Release" и го запазете.

Когато се изпълни, можете да видите, че се извиква дори OnAttack когато бутонът е освободен. isPressed false Тъй като става , също така е възможно да се определи дали това е времето на освобождаване.

Между другото, моля, изтрийте това взаимодействие, защото няма да се използва в бъдеще.

Получаване на информация с Invoke Unity Events

Вторият начин за получаване на входни данни е Invoke Unity Events, така че нека опитаме това. Както бе споменато по-горе, използването на множество методи за въвеждане може да доведе до конфликтна обработка, така че ако е активирана друга обработка, деактивирайте я.

Първо, поставете текстовия обект, така че входната информация да може да бъде показана.

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

Добавете вход > въвеждане на плейъра към празния обект.

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

Създаване на скрипт. Името е произволно, но в случая 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 на метода, което се извиква, когато потребителят взаимодейства с него, е , както в случая с Send Messages. В Invoke Unity Events можете да зададете името на този метод, както желаете.

Когато всеки е извикан, той се подава като InputAction.CallbackContext аргумент, така че можете да получите входното състояние от там. Ако зададете "стойност" в действието, можете да я получите в метода, а ако ReadValue зададете ReadValueAsButton "бутон", можете да я получите в метода.

След като запишете скрипта, прикачете Player Input към обекта, който задавате, и задайте обекта с показван текст.

След това разгънете "Event" и "Action Map Name (SideScrollActionMap)" в Player Input и трябва да видите действията "Move" и "Attack", които сте създали.

Първо, кликнете върху бутона + в Преместване, за да го добавите.

Обектът в долния ляв ъгъл е ваш собствен обект, а функцията е настроена на метода, който току-що сте създали 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 .

Въпреки това, тъй като задаваме събитието само тук, трябва да извикаме метода, когато Enable е извикан, за да активираме OnEnable картата на действието.

Също така, тъй като входното поведение на потребителя се третира като глобална операция, За да предотвратим OnDisable допълнителното действие на картата на действията, след като този обект е невалиден, извикваме метода в Disable метода, за да го деактивираме.

След като запишете скрипта, прикачете го към празния обект, който сте създали, и задайте текстовия обект за показване.

Стартирайте играта, за да видите как работи.

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

Между другото, ако не сте задали взаимодействия в картата на действията за Attack, тя няма да бъде извикана, когато OnAttack освободите бутона.

За да се справите с това, трябва да canceled организирате събитие. Ако не искате да извършвате специална обработка при (0, 0), можете да извикате метода такъв, какъвто е OnMove . Същото важи и за атаката.

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.