Usar mapas de acción para asignar botones a los comportamientos del juego

Actualización de la página :
Fecha de creación de la página :

Entorno de verificación

Windows
  • Ventanas 11
Unity Editor
  • 2020.3.25f1
Paquete del sistema de entrada
  • 1.2.0

Requisitos previos para esta sugerencia

Los siguientes ajustes se han realizado de antemano como premisa para la descripción de este consejo.

Acerca de Action Maps

Los programas de entrada de usuario en teclados, ratones y gamepads básicamente indicaban que se realizaba una determinada acción cuando se presionaba un botón. En el mapa de acción, por ejemplo, puede definir la acción de "saltar" y asignarle botones de controlador y teclas del teclado. Como resultado, el programa solo necesita describir el proceso cuando se realiza una acción específica. Incluso si asigna un botón en otro controlador como una ocurrencia tardía, puede aplicarlo sin cambiar el programa operativo.

Creación de un mapa de acción

Aquí, me gustaría crear un mapa de acción y mostrar la información de entrada del usuario en el texto. Hay varias formas de obtener la entrada del usuario mediante Action Maps.

Haga clic con el botón secundario en cualquier carpeta del proyecto para crear una acción de entrada. La ubicación de la carpeta que se va a crear es arbitraria, pero por favor adminístrela de acuerdo con su proyecto. El nombre del archivo también es arbitrario, pero aquí InputActionSample está .

Al hacer doble clic en el archivo creado, se mostrará la siguiente ventana.

Primero, haga clic en el botón + en Action Maps para crear un mapa de acción. Como unidad de creación, si el contenido de la operación cambia dependiendo de la escena, se definirá en esa unidad. Por ejemplo, en el caso de un juego de acción de desplazamiento lateral, el contenido de la operación cambia durante la acción y en el menú, por lo que creará un mapa de acción para cada uno.

Aquí, como ejemplo, definimos una acción de desplazamiento lateral y la llamamos "SideScrollActionMap".

A continuación, cree Acciones. Como es una muestra, no haré muchas de ellas, pero aquí crearemos acciones de "Mover" para movimiento y "Ataque" para ataque. Como ya se ha creado uno, cambie el nombre o cree uno nuevo, haga clic en el botón + en la esquina superior derecha e ingréselo.

En primer lugar, configure la configuración de Move. El controlador asume que usa las teclas del stick, el D-pad y el cursor del teclado. En el caso de una acción de desplazamiento lateral, hay casos en los que solo se usan izquierda y derecha, pero aquí asumimos que usa cuatro direcciones considerando saltar con la tecla superior y agacharse con la tecla abajo.

Cuando selecciona Mover, hay una selección de Tipo de acción a la derecha, así que configúrela en "Valor".

Verá el Tipo de control a continuación, así que seleccione Vector2. Esto se debe a que la parte superior e inferior se asignan a Y, y la izquierda y la derecha se asignan a X.

A continuación, seleccione la clave que desea asignar a este evento. Seleccione Sin enlace en el medio y seleccione Ruta a la derecha. Aquí seleccionamos el GamePad LeftStick.

Esto une el LeftStick del GamePad al movimiento.

Para vincular también otros controladores, seleccione "Agregar enlace" en el botón + a la derecha de Mover.

Ahora que se ha agregado el No Binding, asignamos un Dpad para el GamePad.

De esta manera, puede agregar el tipo de controlador que desea soportar, así como las teclas y los palos. También es posible configurarlo específicamente para una consola de juegos específica.

Los sticks y los Dpads son botones que asumen arriba, abajo, izquierda y derecha, por lo que se pueden agregar con esto, pero en el caso de los teclados, todos son teclas individuales, por lo que no hay definición para arriba, abajo, izquierda y derecha. Para configurar el teclado hacia arriba, abajo, izquierda o derecha, seleccione Agregar arriba abajo Compuesto izquierdo derecho en el botón +.

Luego se agregará un vector 2D y puede asignarlo a cada Arriba abajo a la derecha, como se muestra en la figura a continuación.

Por ejemplo, si usa Arriba, configure "Flecha arriba" en su teclado. Por cierto, si tiene problemas para encontrar una tecla, puede seleccionarla fácilmente presionando la tecla de destino mientras hace clic en el botón "Escuchar".

Arriba ahora está configurado en Flecha arriba.

Del mismo modo, establezca Abajo, Izquierda y Derecha y listo.

Por supuesto, no solo se pueden configurar las teclas del cursor, sino también WASD.

A continuación, configure Attack. El ataque es fácil de asignar porque es un solo botón. Primero, seleccione Ataque y asegúrese de que el Tipo de acción sea un botón.

A continuación, seleccione Sin enlace y seleccione el botón que desea asignar desde la ruta.

Si desea agregar más, seleccione "Agregar enlace" en el botón +.

Agregue tantos como necesite. Dado que se trata como un botón, el teclado se puede configurar de la misma manera que un controlador de juegos.

Cuando se completen todas las configuraciones, haga clic en "Guardar recurso" para guardar. Puede cerrar esta ventana.

Finalmente, con el archivo inputactions del proyecto (en este caso, el archivo InputActionSample que creó anteriormente), marque "Generar clase C#" en el inspector. Se agregará el parámetro, pero haga clic en el botón "Aplicar" tal como está.

Esto generará un archivo de script con el mismo nombre. Contiene clases que son útiles para usar mapas de acción de programas.

Cómo recibir información de entrada

Hay varias formas de recibir información basada en un mapa de acción. Este consejo explica tres patrones, pero es mejor centrarse en uno de ellos al hacer un juego. Si los usa por separado, será problemático de administrar.

Además, si utiliza varios métodos de recepción de entrada en una sola escena, el procesamiento puede entrar en conflicto interno y no funcionar correctamente.

Recibir información de entrada en Enviar mensajes

El primer método aquí es cómo recibir información de entrada en "Enviar mensajes".

Esta vez, quiero mostrar la información introducida en el texto, por lo que colocaré un objeto de texto.

Además, dado que esta sugerencia intentará obtener información de entrada múltiple, crearemos un objeto vacío para establecer el componente por separado. El nombre puede ser cualquier cosa.

A continuación, agregue un componente Player Input al objeto vacío. Player Input es un componente importante para conectar mapas de acción y scripts.

En "Agregar componente", hay "Entrada del jugador" en la categoría "Entrada", así que agréguela.

Una vez que se agregue el componente Entrada del jugador, establezca el mapa de acción que creó en "Acciones". Suéltelo del proyecto o selecciónelo en el icono + a la derecha.

Compruebe que el mapa predeterminado es el que creó en el mapa de acción.

Verifique que el comportamiento es "Enviar mensajes".

A continuación, cree un script. El nombre del archivo puede ser cualquier cosa, pero aquí InputSendMessage está .

El script tiene este aspecto:

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}";
  }
}
  • El objeto tiene una entrada de reproductor adjunta que establece Enviar mensajes
  • Heredar de MonoBehaviour

Si se cumplen las condiciones, entonces si define un método llamado "OnXXXXXXXX", Se llamará al método de destino cuando se realice la operación de acción especificada. "XXXXXXXX" es el nombre de las acciones creadas en el mapa de acción. Aquí, hemos creado acciones "Mover" y "Atacar", por lo que los nombres de los métodos son "OnMove" y "OnAttack", respectivamente.

OnMove Puede obtener la cantidad introducida desde el argumento InputValue de . Dado que el Tipo de control se establece en "Vector 2", el valor InputValue.Get<Vector2> de entrada se recibirá en .

OnAttackInputValue.isPressed Puede obtener si también está presionando.

Después de guardar el script, adjúntelo a un objeto que tenga un componente Player Input. Establezca también el objeto de texto para su visualización.

Ejecuta el juego y echa un vistazo. Esta vez, he incluido la definición del gamepad y el teclado, por lo que debería funcionar sin importar cuál opere.

Como puede ver cuando lo mueve, puede ver que se llama al método solo cuando hay un cambio en el valor del estado anterior. Por ejemplo, al mover el palo hacia la izquierda, se llama decididamente, pero no hacia la izquierda (- OnMove 1,0). OnMove El botón Ataque también responde solo en el momento en que se presiona, y si se presiona y se mantiene, no se llama al método.

Por lo tanto, creo que el uso ideal no es realizar el procesamiento del juego cuando se llama a OnXXXXXXXX, sino mantener solo el contenido de entrada y usar esos valores en el procesamiento de actualizaciones del juego.

Por cierto, en el estado actual, no se llama cuando se suelta el botón, por lo que no es posible determinar cuándo OnAttack se libera el botón. Para responder a esto, seleccione la acción Ataque que define el botón en la configuración del mapa de acción y agregue "Presionar" desde "Interacciones". Después de eso, establezca el Comportamiento de activación de la prensa agregada en "Presionar y soltar" y guárdelo.

Cuando se ejecuta, puede ver que se llama incluso OnAttack cuando se suelta el botón. isPressed false Dado que se convierte en , también es posible determinar si es el momento de lanzamiento.

Por cierto, elimine esta interacción porque no se utilizará en el futuro.

Recibir información con Invoke Unity Events

Una segunda forma de recibir información es Invoke Unity Events, así que probemos esto. Como se mencionó anteriormente, el uso de múltiples métodos de entrada puede causar un procesamiento conflictivo, por lo que si otro procesamiento está habilitado, desactívelo.

En primer lugar, coloque el objeto de texto de modo que se pueda mostrar la información de entrada.

Invoke Unity Events crea un objeto vacío que realiza operaciones relacionadas.

Agregar entrada > entrada del reproductor al objeto vacío.

Establezca el archivo de mapa de acciones que creó para Actions (en este caso, InputActionSample) y establezca el mapa de acciones que creó (en este caso, SideScrollActionMap) en Default Map. Establezca el comportamiento para invocar eventos de Unity.

Cree un script. El nombre es arbitrario, pero en este caso InputInvokeUnityEvents es .

El script tiene este aspecto:

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 nombre OnMoveOnAttack del método al que se llama cuando el usuario interactúa con él es , como en el caso de Enviar mensajes. En Invoke Unity Events, puedes establecer este nombre de método como quieras.

Cuando se llama a cada uno, se pasa como un InputAction.CallbackContext argumento, por lo que puede obtener el estado de entrada desde allí. Si establece un "valor" en la acción, puede recibirlo en el método, y si ReadValue establece ReadValueAsButton un "botón", puede recibirlo en el método.

Después de guardar el script, adjunte la entrada del reproductor al objeto que está configurando y establezca el objeto de texto para mostrar.

A continuación, expanda "Evento" y "Nombre del mapa de acción (SideScrollActionMap)" en Entrada del jugador y debería ver las acciones "Mover" y "Atacar" que creó.

Primero, haga clic en el botón + en Mover para agregarlo.

El objeto de la esquina inferior izquierda es su propio objeto, y la función se establece en el método que acaba de crear OnMove .

Configure también el evento Attack.

Ejecuta el juego para ver cómo funciona.

Básicamente, se llama solo cuando cambia el mismo valor que Enviar mensajes, pero por alguna razón se puede llamar al método dos veces al mismo tiempo. No sé la causa, pero creo que probablemente se deba a que el proceso de inicio y el proceso continuo se están ejecutando al mismo tiempo. Sin embargo, creo que no hay problema si mantiene solo el valor ingresado como en el caso de Enviar mensajes y realiza el procesamiento real del juego por separado en el proceso de actualización.

Usar un script generado automáticamente para recibir información de entrada

En la tercera sección se describe cómo obtener información de entrada mediante un script generado a partir de un archivo de mapa de acciones.

Dado que existe la posibilidad de conflictos con otros procesos de adquisición, deshabilite otros procesos de adquisición.

Coloque un objeto de texto para mostrar la información de entrada.

Además, cree un objeto vacío para recuperar información de entrada. Este artículo utiliza un script generado automáticamente, por lo que no es necesario agregar Player Input.

El script generado automáticamente a partir del mapa de acción es solo una biblioteca, así que cree un script de control independiente. El nombre es arbitrario, pero en este caso InputScript es .

El script tiene este aspecto:

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

Defina una clase InputActionSample generada automáticamente a partir del mapa de acción en el campo. Esta clase define cada conjunto de acciones en el mapa de acciones y puede establecer los eventos a los que se llama cuando se realizan esas acciones.

Awake En el método, InputActionSample se crea una instancia de y se establece el evento llamado en el momento de la acción. Al OnMoverealizar estas operaciones, ahora se llama al método , OnAttack .

Sin embargo, dado que solo establecemos el evento aquí, debemos OnEnable llamar al método cuando Enable se llama para habilitar el mapa de acción.

Además, dado que el comportamiento de entrada del usuario se trata como una operación global, Para evitar que OnDisable el mapa de acción haga más después de que este objeto se invalide, llamamos al método en Disable el método para deshabilitarlo.

Después de guardar el script, adjúntelo al objeto vacío que creó y establezca el objeto de texto para su visualización.

Ejecuta el juego para ver cómo funciona.

Como puede ver, no se llama al método cuando OnMove la operación Mover se convierte en (0, 0). No estoy seguro de por qué, pero parece que el evento realizado solo toma el que tiene habilitadas las pulsaciones de teclas.

Por cierto, si no ha configurado Interacciones en el mapa de acción para Ataque, no se llamará cuando OnAttack suelte el botón.

Para canceled manejar esto, debe configurar un evento. Si no desea realizar un procesamiento especial en (0, 0), puede llamar al método tal como está OnMove . Lo mismo es cierto para 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);   // 追加
}

Ejecute y compruebe que aparece Move:(0, 0) o Attack:False.