Utilizzare le mappe di azione per assegnare pulsanti ai comportamenti di gioco

Pagina aggiornata :
Data di creazione della pagina :

Ambiente di verifica

Finestre
  • Windows 11
Unity Editor
  • 2020.3.25F1
Pacchetto del sistema di input
  • 1.2.0

Prerequisiti per questo suggerimento

Le seguenti impostazioni sono state effettuate in anticipo come premessa per la descrizione di questo suggerimento.

Informazioni sulle mappe d'azione

I programmi di input dell'utente su tastiere, mouse e gamepad hanno sostanzialmente dichiarato che una determinata azione è stata eseguita quando è stato premuto un pulsante. Nella mappa delle azioni, ad esempio, è possibile definire l'azione di "salto" e assegnarle i pulsanti del controller e i tasti della tastiera. Di conseguenza, il programma deve solo descrivere il processo quando viene eseguita un'azione specifica. Anche se si assegna un pulsante su un altro controller come ripensamento, è possibile applicarlo senza modificare il programma operativo.

Creazione di una mappa delle azioni

Qui, vorrei creare una mappa delle azioni e visualizzare le informazioni di input dell'utente nel testo. Esistono diversi modi per ottenere l'input dell'utente utilizzando le mappe delle azioni.

Fare clic con il pulsante destro del mouse su qualsiasi cartella del progetto per creare un'azione di input. La posizione della cartella da creare è arbitraria, ma gestiscila in base al tuo progetto. Anche il nome del file è arbitrario, ma eccolo qui InputActionSample .

Quando si fa doppio clic sul file creato, verrà visualizzata la seguente finestra.

Innanzitutto, fai clic sul pulsante + in Action Map per creare una action map. Come unità di creazione, se il contenuto dell'operazione cambia a seconda della scena, verrà definito in tale unità. Ad esempio, nel caso di un gioco d'azione a scorrimento laterale, il contenuto dell'operazione cambia durante l'azione e nel menu, quindi creerai una mappa delle azioni per ciascuno.

Qui, ad esempio, definiamo un'azione di scorrimento laterale e la chiamiamo "SideScrollActionMap".

Quindi, crea azioni. Poiché è un esempio, non ne farò molti, ma qui creeremo azioni "Move" per il movimento e "Attack" per l'attacco. Poiché uno è già stato creato, cambia il nome o creane uno nuovo, fai clic sul pulsante + nell'angolo in alto a destra e inseriscilo.

Innanzitutto, configurare la configurazione Sposta. Il controller presuppone che si utilizzino i tasti stick, D-pad e cursore della tastiera. Nel caso di un'azione a scorrimento laterale, ci sono casi in cui vengono utilizzati solo sinistra e destra, ma qui supponiamo che tu usi quattro direzioni considerando di saltare con il tasto superiore e accovacciarti con il tasto giù.

Quando selezioni Sposta, c'è una selezione Tipo di azione a destra, quindi imposta questo su "Valore".

Vedrai il Tipo di controllo qui sotto, quindi seleziona Vector2. Questo perché la parte superiore e inferiore sono assegnate a Y e la sinistra e la destra sono assegnate a X.

Selezionare quindi la chiave che si desidera assegnare a questo evento. Selezionare Nessuna associazione al centro e selezionare Percorso a destra. Qui selezioniamo il GamePad LeftStick.

Questo lega la levetta sinistra del GamePad alla mossa.

Per associare anche altri controller, seleziona "Aggiungi associazione" dal pulsante + a destra di Sposta.

Ora che è stato aggiunto No Binding, assegniamo un Dpad per il GamePad.

In questo modo, è possibile aggiungere il tipo di controller che si desidera supportare, nonché i tasti e le levette. È anche possibile impostarlo specificamente per una console di gioco specifica.

Stick e Dpad sono pulsanti che assumono su, giù, sinistra e destra, quindi possono essere aggiunti con questo, ma nel caso delle tastiere, sono tutti tasti singoli, quindi non esiste una definizione per su, giù, sinistra e destra. Per impostare la tastiera su, giù, sinistra o destra, selezionare Aggiungi su giù a sinistra destra composito dal pulsante +.

Verrà quindi aggiunto un vettore 2D e sarà possibile assegnarlo a ciascun Up Down Left Right, come mostrato nella figura seguente.

Ad esempio, se si utilizza Su, impostare "Freccia su" sulla tastiera. A proposito, se hai difficoltà a trovare una chiave, puoi facilmente selezionarla premendo il tasto di destinazione mentre fai clic sul pulsante "Ascolta".

Su è ora impostato su Freccia su.

Allo stesso modo, imposta Giù, Sinistra e Destra e il gioco è fatto.

Naturalmente, non solo i tasti cursore ma anche WASD possono essere impostati.

Quindi, configurare Attack. L'attacco è facile da assegnare perché è un singolo pulsante. Innanzitutto, seleziona Attacco e assicurati che il Tipo di azione sia un pulsante.

Quindi selezionare Nessun binding e selezionare il pulsante che si desidera assegnare dal percorso.

Se desideri aggiungerne altri, seleziona "Aggiungi associazione" dal pulsante +.

Aggiungine quanti ne hai bisogno. Poiché viene trattato come un pulsante, la tastiera può essere impostata allo stesso modo di un controller di gioco.

Quando tutte le impostazioni sono complete, fai clic su "Salva risorsa" per salvare. È possibile chiudere questa finestra.

Infine, con il file inputactions del progetto (in questo caso, il file InputActionSample creato in precedenza), selezionare "Genera classe C#" nell'ispettore. Il parametro verrà aggiunto, ma fai clic sul pulsante "Applica" così com'è.

Verrà generato un file di script con lo stesso nome. Contiene classi utili per l'utilizzo di action map dai programmi.

Come ricevere le informazioni di input

Esistono diversi modi per ricevere input in base a una mappa delle azioni. Questo suggerimento spiega tre modelli, ma è meglio concentrarsi su uno di essi quando si crea effettivamente un gioco. Se li usi separatamente, sarà problematico da gestire.

Inoltre, se si utilizzano più metodi di ricezione dell'input in una singola scena, l'elaborazione potrebbe entrare in conflitto internamente e non funzionare correttamente.

Ricevere informazioni di input in Invia messaggi

Il primo metodo qui è come ricevere informazioni di input in "Invia messaggi".

Questa volta, voglio visualizzare le informazioni inserite nel testo, quindi posizionerò un oggetto di testo.

Inoltre, poiché questo suggerimento cercherà di ottenere più informazioni di input, creeremo un oggetto vuoto per impostare il componente separatamente. Il nome può essere qualsiasi cosa.

Quindi, aggiungere un componente di input del lettore all'oggetto vuoto. L'input del giocatore è un componente importante per la connessione di mappe di azione e script.

In "Aggiungi componente", c'è "Player Input" nella categoria "Input", quindi aggiungilo.

Una volta aggiunto il componente Player Input, imposta la mappa delle azioni che hai creato in "Azioni". Rilascialo dal progetto o selezionalo dall'icona + a destra.

Verificare che la mappa predefinita sia quella creata nella mappa delle azioni.

Verificare che il comportamento sia "Invia messaggi".

Quindi, creare uno script. Il nome del file può essere qualsiasi cosa, ma eccolo qui InputSendMessage .

Lo script è simile al seguente:

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}";
  }
}
  • All'oggetto è associato un input del lettore che imposta Invia messaggi
  • Ereditare da MonoBehaviour

Se le condizioni sono soddisfatte, se si definisce un metodo denominato "OnXXXXXXXX", Il metodo di destinazione verrà chiamato quando viene eseguita l'operazione di azione specificata. "XXXXXXXX" è il nome delle azioni create nella mappa delle azioni. Qui, abbiamo creato le azioni "Move" e "Attack", quindi i nomi dei metodi sono rispettivamente "OnMove" e "OnAttack".

OnMove È possibile ottenere l'importo immesso dall'argomento InputValue di . Poiché il tipo di controllo è impostato su "Vector 2", il valore InputValue.Get<Vector2> di input verrà ricevuto in .

OnAttackInputValue.isPressed Puoi capire se stai premendo pure.

Dopo aver salvato lo script, associarlo a un oggetto che dispone di un componente di input del lettore. Impostare anche l'oggetto di testo per la visualizzazione.

Esegui il gioco e dai un'occhiata. Questa volta, ho incluso la definizione del gamepad e della tastiera, quindi dovrebbe funzionare indipendentemente da quale si opera.

Come si può vedere quando lo si sposta, è possibile vedere che il metodo viene chiamato solo quando c'è una modifica di valore dallo stato precedente. Ad esempio, mentre si sposta il bastone a sinistra, viene chiamato in modo univoco, ma non a sinistra (- OnMove 1,0). OnMove Anche il pulsante Attacco risponde solo nel momento in cui viene premuto e, se viene premuto e premuto, il metodo non viene chiamato.

Pertanto, penso che l'uso ideale non sia quello di eseguire l'elaborazione del gioco quando viene chiamato OnXXXXXXXX, ma di mantenere solo il contenuto di input e utilizzare quei valori nell'elaborazione degli aggiornamenti del gioco.

A proposito, nello stato attuale, non viene chiamato quando il pulsante viene rilasciato, quindi non è possibile determinare quando OnAttack il pulsante viene rilasciato. Per rispondere a questo, seleziona l'azione Attacco che definisce il pulsante nelle impostazioni della mappa delle azioni e aggiungi "Premi" da "Interazioni". Successivamente, imposta il comportamento di attivazione della stampa aggiunta su "Press And Release" e salvalo.

Quando viene eseguito, puoi vedere che viene chiamato anche OnAttack quando il pulsante viene rilasciato. isPressed false Dal momento che diventa , è anche possibile determinare se è il momento del rilascio.

A proposito, si prega di eliminare questa interazione perché non verrà utilizzata in futuro.

Ricevere input con Invoke Unity Events

Un secondo modo per ricevere input è Invoke Unity Events, quindi proviamo questo. Come accennato in precedenza, l'utilizzo di più metodi di input può causare un'elaborazione in conflitto, quindi se è abilitata un'altra elaborazione, disabilitarla.

Innanzitutto, posizionare l'oggetto di testo in modo che possano essere visualizzate le informazioni di input.

Invoke Unity Events crea un oggetto vuoto che esegue operazioni correlate.

Aggiungere input > Player Input all'oggetto vuoto.

Impostare il file della mappa delle azioni creato per Actions (in questo caso, InputActionSample) e impostare la Action Map creata (in questo caso, SideScrollActionMap) su Default Map. Impostare Comportamento per richiamare gli eventi di unità.

Creare uno script. Il nome è arbitrario, ma in questo caso InputInvokeUnityEvents è .

Lo script è simile al seguente:

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

Il nome OnMoveOnAttack del metodo chiamato quando l'utente interagisce con esso è , come nel caso di Send Messages. In Invoke Unity Events è possibile impostare il nome di questo metodo come desiderato.

Quando ognuno viene chiamato, viene passato come argomento InputAction.CallbackContext , in modo da poter ottenere lo stato di input da lì. Se imposti un "valore" nell'azione, puoi riceverlo nel metodo e se imposti ReadValue ReadValueAsButton un "pulsante", puoi riceverlo nel metodo.

Dopo aver salvato lo script, allegare l'input del lettore all'oggetto impostato e impostare l'oggetto di testo visualizzato.

Quindi, espandi "Evento" e "Nome mappa azione (SideScrollActionMap)" in Input giocatore e dovresti vedere le azioni "Sposta" e "Attacco" che hai creato.

Innanzitutto, fai clic sul pulsante + su Sposta per aggiungerlo.

L'oggetto nell'angolo inferiore sinistro è il tuo oggetto e la funzione è impostata sul metodo appena creato OnMove .

Configurare anche l'evento Attack.

Esegui il gioco per vedere come funziona.

Fondamentalmente, viene chiamato solo quando cambia lo stesso valore di Invia messaggi, ma per qualche motivo il metodo può essere chiamato due volte contemporaneamente. Non conosco la causa, ma penso che sia probabilmente perché il processo di avvio e il processo continuo sono in esecuzione allo stesso tempo. Tuttavia, penso che non ci siano problemi se si mantiene solo il valore inserito come nel caso di Invia messaggi ed eseguire l'elaborazione effettiva del gioco separatamente nel processo di aggiornamento.

Utilizzare uno script generato automaticamente per ricevere informazioni di input

Nella terza sezione viene descritto come ottenere informazioni di input utilizzando uno script generato da un file di action map.

Poiché esiste la possibilità di conflitti con altri processi di acquisizione, si prega di disabilitare altri processi di acquisizione.

Posizionare un oggetto di testo per visualizzare le informazioni di input.

Inoltre, creare un oggetto vuoto per il recupero delle informazioni di input. In questo articolo viene utilizzato uno script generato automaticamente, pertanto non è necessario aggiungere l'input del lettore.

Lo script generato automaticamente dalla mappa delle azioni è solo una libreria, quindi crea uno script di controllo separato. Il nome è arbitrario, ma in questo caso InputScript è .

Lo script è simile al seguente:

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

Definire una classe InputActionSample generata automaticamente dalla mappa delle azioni sul campo. Questa classe definisce ogni set di azioni nella mappa delle azioni ed è possibile impostare gli eventi chiamati quando tali azioni vengono eseguite.

Awake Nel metodo viene InputActionSample creata un'istanza di e viene impostato l'evento chiamato al momento dell'azione. Quando OnMovesi eseguono queste operazioni, viene ora chiamato il metodo , OnAttack .

Tuttavia, poiché impostiamo solo l'evento qui, dobbiamo OnEnable chiamare il metodo quando Enable viene chiamato per abilitare la mappa delle azioni.

Inoltre, poiché il comportamento di input dell'utente viene trattato come un'operazione globale, Per evitare che OnDisable la mappa delle azioni venga eseguita in modo aggiuntivo dopo l'invalidazione di questo oggetto, chiamiamo il metodo nel Disable metodo per disabilitarlo.

Dopo aver salvato lo script, allegarlo all'oggetto vuoto creato e impostare l'oggetto di testo per la visualizzazione.

Esegui il gioco per vedere come funziona.

Come si può vedere, il metodo non viene chiamato quando OnMove l'operazione Move diventa (0, 0). Non sono sicuro del perché, ma sembra che l'evento eseguito prenda solo quello con le sequenze di tasti abilitate.

A proposito, se non hai impostato Interazioni nella mappa d'azione per Attacco, non verrà chiamato quando OnAttack rilasci il pulsante.

Per canceled gestire questo, è necessario impostare un evento. Se non si desidera eseguire un'elaborazione speciale in (0, 0), è possibile chiamare il metodo così com'è OnMove . Lo stesso vale per 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);   // 追加
}

Eseguire e verificare che venga visualizzato Move:(0, 0) o Attack:False.