Utilitzar mapes d'accions per assignar botons als comportaments del joc

Pàgina actualitzada :
Data de creació de la pàgina :

Entorn de verificació

Windows
  • Finestres 11
Editor d'unitat
  • 25.3.2020
Paquet del sistema d'entrada
  • 1.2.0

Requisits previs per a aquest consell

La configuració següent s'ha fet amb antelació com a premissa per a la descripció d'aquest consell.

Sobre els mapes d'acció

Els programes d'entrada d'usuaris en teclats, ratolins i gamepads bàsicament indicaven que es realitzava una determinada acció quan es prem un botó. En el mapa d'accions, per exemple, podeu definir l'acció de "saltar" i assignar-li botons del controlador i tecles del teclat. Com a resultat, el programa només ha de descriure el procés quan es realitza una acció específica. Fins i tot si assigneu un botó a un altre controlador com a reflexió posterior, podeu aplicar-lo sense canviar el programa operatiu.

Creació d'un mapa d'accions

Aquí, m'agradaria crear un mapa d'accions i mostrar la informació d'entrada de l'usuari al text. Hi ha diverses maneres d'obtenir l'entrada de l'usuari mitjançant els mapes d'accions.

Feu clic amb el botó dret a qualsevol carpeta del projecte per crear una acció d'entrada. La ubicació de la carpeta a crear és arbitrària, però si us plau, gestioneu-la segons el vostre projecte. El nom del fitxer també és arbitrari, però aquí InputActionSample és .

Quan feu doble clic al fitxer creat, es mostrarà la finestra següent.

Primer, feu clic al botó + a Mapes d'accions per crear un mapa d'accions. Com a unitat de creació, si el contingut de l'operació canvia en funció de l'escena, es definirà en aquesta unitat. Per exemple, en el cas d'un joc d'acció de desplaçament lateral, el contingut de l'operació canvia durant l'acció i al menú, de manera que creareu un mapa d'accions per a cadascun.

Aquí, com a exemple, definim una acció de desplaçament lateral i l'anomenem "SideScrollActionMap".

A continuació, creeu accions. Com que és una mostra, no en faré moltes, però aquí crearem accions "Mou" per al moviment i "Ataca" per a l'atac. Com que ja se n'ha creat un, canvieu el nom o creeu-ne un de nou, feu clic al botó + a la cantonada superior dreta i introduïu-lo.

Primer, configureu la configuració Mou. El controlador assumeix que utilitzeu el llapis, el coixinet D i les tecles del cursor del teclat. En el cas d'una acció de desplaçament lateral, hi ha casos en què només s'utilitzen esquerra i dreta, però aquí suposem que utilitzeu quatre direccions considerant saltar amb la tecla superior i ajupir-vos amb la tecla avall.

Quan seleccioneu Mou, hi ha una selecció Tipus d'acció a la dreta, de manera que definiu-la com a "Valor".

Veureu el Tipus de control a continuació, així que seleccioneu Vector2. Això es deu al fet que la part superior i inferior estan assignades a Y, i l'esquerra i la dreta s'assignen a X.

A continuació, seleccioneu la clau que voleu assignar a aquest esdeveniment. Seleccioneu Sense vinculació al centre i seleccioneu Camí a la dreta. Aquí seleccionem el GamePad LeftStick.

Això uneix el LeftStick del GamePad al moviment.

Per enllaçar també altres controladors, seleccioneu "Afegeix vinculació" al botó + a la dreta de Mou.

Ara que s'afegeix el No Binding, assignem un Dpad per al GamePad.

D'aquesta manera, podeu afegir el tipus de controlador que vulgueu suportar, així com les tecles i pals. També és possible configurar-lo específicament per a una consola de jocs específica.

Els pals i els dpads són botons que assumeixen amunt, avall, esquerra i dreta, de manera que es poden afegir amb això, però en el cas dels teclats, tots són tecles simples, de manera que no hi ha cap definició per a up, down, left i right. Per configurar el teclat amunt, avall, esquerra o dreta, seleccioneu Afegeix compost dret esquerre des del botó +.

A continuació, s'afegirà un vector 2D i el podeu assignar a cada Up Down Left Right, com es mostra a la figura següent.

Per exemple, si utilitzeu Amunt, configureu "Fletxa amunt" al teclat. Per cert, si teniu problemes per trobar una clau, podeu seleccionar-la fàcilment prement la tecla de destinació mentre feu clic al botó "Escolta".

Ara està configurat com a fletxa amunt.

De la mateixa manera, configureu Avall, Esquerra i Dreta i ja heu acabat.

Per descomptat, no només es poden configurar les tecles del cursor, sinó també WASD.

A continuació, configureu Attack. Attack és fàcil d'assignar perquè és un sol botó. Primer, seleccioneu Ataca i assegureu-vos que el Tipus d'acció sigui un botó.

A continuació, seleccioneu Sense vinculació i seleccioneu el botó que voleu assignar des del camí.

Si voleu afegir-ne més, seleccioneu "Afegeix vinculació" al botó +.

Afegiu-ne tantes com necessiteu. Com que es tracta com un botó, el teclat es pot configurar de la mateixa manera que un comandament de joc.

Quan s'hagin completat totes les configuracions, feu clic a "Desa el recurs" per desar-lo. Podeu tancar aquesta finestra.

Finalment, amb el fitxer inputactions del projecte (en aquest cas, el fitxer InputActionSample que heu creat anteriorment), marqueu "Generar classe C#" a l'inspector. S'afegirà el paràmetre, però feu clic al botó "Aplica" tal com està.

Això generarà un fitxer script amb el mateix nom. Conté classes que són útils per utilitzar mapes d'accions de programes.

Com rebre la informació d'entrada

Hi ha diverses maneres de rebre aportacions basades en un mapa d'accions. Aquest consell explica tres patrons, però és millor centrar-se en un d'ells a l'hora de fer un joc. Si els utilitzeu per separat, serà difícil de gestionar.

A més, si utilitzeu diversos mètodes de recepció d'entrada en una sola escena, el processament pot entrar en conflicte internament i no funcionar correctament.

Rebre informació d'entrada a Enviar missatges

El primer mètode aquí és com rebre informació d'entrada a "Enviar missatges".

Aquesta vegada, vull mostrar la informació introduïda en el text, així que col·locaré un objecte de text.

A més, com que aquest consell intentarà obtenir informació d'entrada múltiple, crearem un objecte buit per establir el component per separat. El nom pot ser qualsevol cosa.

A continuació, afegiu un component d'entrada del reproductor a l'objecte buit. L'entrada del reproductor és un component important per connectar mapes d'accions i scripts.

A "Afegeix component", hi ha "Entrada del reproductor" a la categoria "Entrada", així que afegiu-la.

Un cop afegit el component Entrada del reproductor, definiu el mapa d'accions que heu creat a "Accions". Deixeu-lo anar del projecte o seleccioneu-lo des de la icona + a la dreta.

Verifiqueu que el mapa per defecte sigui el que heu creat al mapa d'accions.

Verifiqueu que el comportament sigui "Envia missatges".

A continuació, creeu un script. El nom del fitxer pot ser qualsevol cosa, però aquí InputSendMessage és .

El guió té aquest aspecte:

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}";
  }
}
  • L'objecte té una entrada del reproductor adjunta que defineix Envia missatges
  • Herència de MonoBehaviour

Si es compleixen les condicions, si definiu un mètode anomenat "OnXXXXXXXX", El mètode objectiu s'anomenarà quan es realitzi l'operació d'acció especificada. "XXXXXXXX" és el nom de les accions creades al mapa d'accions. Aquí, hem creat accions "Move" i "Attack", de manera que els noms del mètode són "OnMove" i "OnAttack", respectivament.

OnMove Podeu obtenir l'import introduït a partir de l'argument InputValue de . Com que el tipus de control està definit com a "Vector 2", el valor InputValue.Get<Vector2> d'entrada es rebrà a .

OnAttackInputValue.isPressed Podeu obtenir si també esteu prement.

Després de desar l'script, adjunta'l a un objecte que tingui un component "Entrada del reproductor". Definiu també l'objecte de text perquè es visualitzi.

Executeu el joc i feu-hi un cop d'ull. Aquesta vegada, he inclòs la definició del gamepad i el teclat, de manera que hauria de funcionar independentment de quin opereu.

Com podeu veure quan el moveu, podeu veure que el mètode només s'anomena quan hi ha un canvi de valor respecte a l'estat anterior. Per exemple, mentre es mou el pal cap a l'esquerra, es diu individualment, però no cap a l'esquerra (- OnMove 1,0). OnMove El botó Ataca també respon només en el moment en què es prem i, si es prem i es manté, no es crida el mètode.

Per tant, crec que l'ús ideal no és realitzar el processament del joc quan es crida OnXXXXXXXX, sinó mantenir només el contingut d'entrada i utilitzar aquests valors en el processament d'actualitzacions del joc.

Per cert, en l'estat actual, no es diu quan es deixa anar el botó, de manera que no és possible determinar quan OnAttack es deixa anar el botó. Per respondre-hi, seleccioneu l'acció Atac que defineix el botó a la configuració del mapa d'accions i afegiu "Prémer" des d'"Interaccions". Després d'això, configureu el comportament d'activació de la premsa afegida a "Prem i allibera" i deseu-lo.

Quan s'executa, es pot veure que es crida fins i tot OnAttack quan es deixa anar el botó. isPressed false Des que es converteix en , també és possible determinar si és el moment del llançament.

Per cert, si us plau, suprimiu aquesta interacció perquè no s'utilitzarà en el futur.

Rebre aportacions amb Invoke Unity Events

Una segona manera de rebre aportacions és Invoke Unity Events, així que provem-ho. Com s'ha esmentat anteriorment, l'ús de diversos mètodes d'entrada pot causar un processament conflictiu, de manera que si s'habilita un altre processament, desactiveu-lo.

Primer, col·loqueu l'objecte de text de manera que es pugui mostrar la informació d'entrada.

Invoke Unity Events crea un objecte buit que realitza operacions relacionades.

Afegiu Entrada > Entrada del reproductor a l'objecte buit.

Definiu el fitxer de mapa d'accions que heu creat per a Actions (en aquest cas, InputActionSample) i definiu el mapa d'accions que heu creat (en aquest cas, SideScrollActionMap) a Mapa per defecte. Definiu Comportament per invocar esdeveniments d'unitat.

Creeu un script. El nom és arbitrari, però en aquest cas InputInvokeUnityEvents és .

El guió té aquest aspecte:

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}";
  }
}

El nom OnMoveOnAttack del mètode que s'anomena quan l'usuari interactua amb ell és , com en el cas d'Enviar missatges. A Invoca esdeveniments d'unitat, podeu definir el nom d'aquest mètode com vulgueu.

Quan es crida cadascun, es passa com a InputAction.CallbackContext argument, de manera que podeu obtenir l'estat d'entrada des d'allà. Si establiu un "valor" a l'acció, podeu rebre'l al mètode i, si establiu ReadValue ReadValueAsButton un "botó", el podeu rebre al mètode.

Després de desar l'script, adjunteu l'entrada del reproductor a l'objecte que esteu configurant i configureu l'objecte de text de visualització.

A continuació, expandiu "Esdeveniment" i "Nom del mapa d'accions (SideScrollActionMap)" a Entrada del jugador i hauríeu de veure les accions "Mou" i "Ataca" que heu creat.

Primer, feu clic al botó + de Mou per afegir-lo.

L'objecte de la cantonada inferior esquerra és el vostre propi objecte, i la funció s'estableix segons el mètode que acabeu de crear OnMove .

Configureu també l'esdeveniment Attack.

Executeu el joc per veure com funciona.

Bàsicament, només es diu quan canvia el mateix valor que Envia missatges, però per alguna raó el mètode es pot cridar dues vegades al mateix temps. Desconec la causa, però crec que probablement és perquè el procés d'inici i el procés continu s'estan executant alhora. Tanmateix, crec que no hi ha cap problema si manteniu només el valor introduït com en el cas d'Envia missatges i realitzeu el processament real del joc per separat en el procés d'actualització.

Utilitzar un script generat automàticament per rebre informació d'entrada

La tercera secció descriu com obtenir informació d'entrada mitjançant un script generat a partir d'un fitxer de mapa d'accions.

Atès que hi ha possibilitat de conflictes amb altres processos d'adquisició, es prega desactivar altres processos d'adquisició.

Col·loqueu un objecte de text per mostrar la informació d'entrada.

A més, creeu un objecte buit per recuperar informació d'entrada. Aquest article utilitza un script generat automàticament, de manera que no cal que afegiu l'entrada del reproductor.

L'script generat automàticament a partir del mapa d'accions és només una biblioteca, de manera que creeu un script de control independent. El nom és arbitrari, però en aquest cas InputScript és .

El guió té aquest aspecte:

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}";
  }
}

Definiu una classe InputActionSample generada automàticament a partir del mapa d'accions del camp. Aquesta classe defineix cada acció definida al mapa d'accions i podeu definir els esdeveniments que s'anomenen quan es realitzen aquestes accions.

Awake En el mètode, InputActionSample es crea una instància de i es defineix l'esdeveniment cridat en el moment de l'acció. Quan OnMoverealitzeu aquestes operacions, ara s'anomena el mètode , OnAttack .

Tanmateix, com que només establim l'esdeveniment aquí, OnEnable hem de cridar el mètode quan Enable es crida per habilitar el mapa d'accions.

A més, atès que el comportament d'entrada de l'usuari es tracta com una operació global, Per evitar que OnDisable el mapa d'accions faci més després d'invalidar aquest objecte, cridem el mètode al Disable mètode per desactivar-lo.

Després de desar l'script, adjunteu-lo a l'objecte buit que heu creat i configureu l'objecte de text perquè es mostri.

Executeu el joc per veure com funciona.

Com podeu veure, el mètode no s'anomena quan OnMove l'operació Mou esdevé (0, 0). No estic segur de per què, però sembla que l'esdeveniment realitzat només pren en realitat el que té les pulsacions de tecles habilitades.

Per cert, si no heu definit Interaccions al mapa d'accions d'Attack, no es trucarà quan OnAttack deixeu anar el botó.

Per gestionar-ho canceled , heu de configurar un esdeveniment. Si no voleu realitzar un processament especial a (0, 0), podeu trucar al mètode tal com és OnMove . El mateix passa amb 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);   // 追加
}

Executeu i verifiqueu que apareguin Mou:(0, 0) o Atac:Fals .