Actiekaarten gebruiken om knoppen toe te wijzen aan gamegedrag

Pagina bijgewerkt :
Aanmaakdatum van pagina :

Verificatieomgeving

Ramen
  • Voor Windows 11
Unity Editor
  • 2020.3.25f1
Input systeem pakket
  • 1.2.0

Vereisten voor deze tip

De volgende instellingen zijn vooraf gemaakt als uitgangspunt voor de beschrijving van deze tip.

Informatie over actiekaarten

Gebruikersinvoerprogramma's op toetsenborden, muizen en gamepads stelden in feite dat een bepaalde actie werd uitgevoerd wanneer een knop werd ingedrukt. In de actiekaart kunt u bijvoorbeeld de actie van "springen" definiëren en er controllerknoppen en toetsenbordtoetsen aan toewijzen. Als gevolg hiervan hoeft het programma het proces alleen te beschrijven wanneer een specifieke actie wordt uitgevoerd. Zelfs als u een knop op een andere controller als bijzaak toewijst, kunt u deze toepassen zonder het besturingsprogramma te wijzigen.

Een actiekaart maken

Hier wil ik een actiekaart maken en de invoerinformatie van de gebruiker in de tekst weergeven. Er zijn verschillende manieren om gebruikersinvoer te krijgen met behulp van Action Maps.

Klik met de rechtermuisknop op een map in het project om een invoeractie te maken. De locatie van de map die moet worden gemaakt is willekeurig, maar beheer deze volgens uw project. De bestandsnaam is ook willekeurig, maar hier InputActionSample is het .

Wanneer u dubbelklikt op het gemaakte bestand, wordt het volgende venster weergegeven.

Klik eerst op de knop + in Action Maps om een actiekaart te maken. Als een creatie-eenheid, als de inhoud van de bewerking verandert afhankelijk van de scène, wordt deze in die eenheid gedefinieerd. In het geval van een side-scrolling actiespel verandert bijvoorbeeld de inhoud van de bewerking tijdens de actie en in het menu, zodat u voor elk een actiekaart maakt.

Hier definiëren we als voorbeeld een side-scrolling actie en noemen deze "SideScrollActionMap".

Maak vervolgens Acties. Omdat het een voorbeeld is, zal ik er niet veel van maken, maar hier zullen we "Move" -acties maken voor beweging en "Attack" voor aanval. Aangezien er al een is gemaakt, wijzigt u de naam of maakt u een nieuwe, klikt u op de knop + in de rechterbovenhoek en voert u deze in.

Configureer eerst de configuratie Verplaatsen. De controller gaat ervan uit dat u de stick, D-pad en toetsenbordcursortoetsen gebruikt. In het geval van een side-scrolling actie zijn er gevallen waarin alleen links en rechts worden gebruikt, maar hier gaan we ervan uit dat je vier richtingen gebruikt, gezien het springen met de bovenste toets en hurken met de down-toets.

Wanneer u Verplaatsen selecteert, is er een actietypeselectie aan de rechterkant, dus stel deze in op "Waarde".

U ziet het besturingstype hieronder, dus selecteer Vector2. Dit komt omdat de boven- en onderkant zijn toegewezen aan Y en de linker- en rechterkant aan X.

Selecteer vervolgens de sleutel die u aan deze gebeurtenis wilt toewijzen. Selecteer Geen binding in het midden en selecteer Pad aan de rechterkant. Hier selecteren we de GamePad LeftStick.

Dit bindt de LeftStick van de GamePad aan de Move.

Als u ook andere controllers wilt binden, selecteert u "Binding toevoegen" op de knop + rechts van Verplaatsen.

Nu de No Binding is toegevoegd, wijzen we een Dpad toe voor de GamePad.

Op deze manier kunt u het type controller toevoegen dat u wilt ondersteunen, evenals de toetsen en sticks. Het is ook mogelijk om het specifiek voor een specifieke spelcomputer in te stellen.

Sticks en Dpads zijn knoppen die uitgaan van omhoog, omlaag, links en rechts, dus ze kunnen hiermee worden toegevoegd, maar in het geval van toetsenborden zijn het allemaal enkele toetsen, dus er is geen definitie voor omhoog, omlaag, links en rechts. Als u het toetsenbord omhoog, omlaag, links of rechts wilt instellen, selecteert u Omlaag naar links rechts samengesteld uit de + knop.

Er wordt dan een 2D-vector toegevoegd en u kunt deze toewijzen aan elke Omhoog Linksboven Rechts, zoals weergegeven in de onderstaande afbeelding.

Als u bijvoorbeeld Omhoog gebruikt, stelt u 'Pijl-omhoog' in op uw toetsenbord. Trouwens, als u lastig bent om een toets te vinden, kunt u deze eenvoudig selecteren door op de doeltoets te drukken terwijl u op de knop "Luisteren" klikt.

Omhoog is nu ingesteld op Pijl-omhoog.

Stel op dezelfde manier Neer, Links en Rechts in en je bent klaar.

Natuurlijk kunnen niet alleen cursortoetsen, maar ook WASD worden ingesteld.

Configureer vervolgens Attack. Attack is eenvoudig toe te wijzen omdat het een enkele knop is. Selecteer eerst Aanval en zorg ervoor dat het actietype een knop is.

Selecteer vervolgens Geen binding en selecteer de knop die u wilt toewijzen in het pad.

Als u meer wilt toevoegen, selecteert u "Binding toevoegen" op de knop + .

Voeg er zoveel toe als je nodig hebt. Omdat het wordt behandeld als een knop, kan het toetsenbord op dezelfde manier worden ingesteld als een gamecontroller.

Wanneer alle instellingen zijn voltooid, klikt u op "Asset opslaan" om op te slaan. U kunt dit venster sluiten.

Ten slotte vinkt u met het bestand inputactions van het project (in dit geval het InputActionSample-bestand dat u eerder hebt gemaakt) "C# Class genereren" aan in de controle. De parameter wordt toegevoegd, maar klik op de knop "Toepassen" zoals deze is.

Hiermee wordt een scriptbestand met dezelfde naam gegenereerd. Het bevat klassen die handig zijn voor het gebruik van actiekaarten van programma's.

Hoe invoerinformatie te ontvangen

Er zijn verschillende manieren om input te ontvangen op basis van een actiekaart. Deze tip legt drie patronen uit, maar het is beter om je op een van hen te concentreren wanneer je daadwerkelijk een spel maakt. Als u ze afzonderlijk gebruikt, is het lastig om te beheren.

Als u meerdere methoden voor het ontvangen van invoer in één scène gebruikt, kan de verwerking intern conflicteren en niet correct werken.

Invoergegevens ontvangen in Berichten verzenden

De eerste methode hier is hoe u invoerinformatie kunt ontvangen in "Berichten verzenden".

Deze keer wil ik de ingevoerde informatie in de tekst weergeven, dus ik zal een tekstobject plaatsen.

Omdat deze tip ook probeert meerdere invoerinformatie te krijgen, maken we een leeg object om de component afzonderlijk in te stellen. De naam kan van alles zijn.

Voeg vervolgens een component Spelerinvoer toe aan het lege object. Player Input is een belangrijk onderdeel voor het verbinden van action maps en scripts.

In "Component toevoegen" is er "Player Input" in de categorie "Input", dus voeg het toe.

Zodra de component Spelerinvoer is toegevoegd, stelt u de actiekaart in die u hebt gemaakt in "Acties". Zet het neer uit het project of selecteer het in het pictogram + aan de rechterkant.

Controleer of de standaardkaart de kaart is die u in de actiekaart hebt gemaakt.

Controleer of het gedrag 'Berichten verzenden' is.

Maak vervolgens een script. De bestandsnaam kan van alles zijn, maar hier InputSendMessage is het .

Het script ziet er als volgt uit:

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}";
  }
}
  • Aan het object is een spelerinvoer gekoppeld waarmee Berichten verzenden wordt ingesteld
  • Erven van MonoBehaviour

Als aan de voorwaarden is voldaan, als u een methode definieert met de naam "OnXXXXXXXX", De doelmethode wordt aangeroepen wanneer de opgegeven actiebewerking wordt uitgevoerd. "XXXXXXXX" is de naam van de acties die in de actiekaart zijn gemaakt. Hier hebben we acties "Verplaatsen" en "Aanvallen" gemaakt, dus de methodenamen zijn respectievelijk "OnMove" en "OnAttack".

OnMove U kunt het ingevoerde bedrag ophalen uit het argument InputValue van . Aangezien het besturingstype is ingesteld op "Vector 2", wordt de invoerwaarde InputValue.Get<Vector2> ontvangen in .

OnAttackInputValue.isPressed Je kunt ook krijgen of je indrukt.

Nadat u het script hebt opgeslagen, koppelt u het aan een object met een component Spelerinvoer. Stel het tekstobject ook in voor weergave.

Voer het spel uit en neem een kijkje. Deze keer heb ik de definitie van de gamepad en het toetsenbord opgenomen, dus het zou moeten werken, ongeacht welke je bedient.

Zoals u kunt zien wanneer u het verplaatst, kunt u zien dat de methode alleen wordt aangeroepen wanneer er een waardewijziging is ten opzichte van de vorige status. Als je bijvoorbeeld de stick naar links beweegt, wordt deze eenzijdig genoemd, maar niet naar links (- OnMove 1,0). OnMove De Attack-knop reageert ook alleen op het moment dat deze wordt ingedrukt en als deze wordt ingedrukt en vastgehouden, wordt de methode niet aangeroepen.

Daarom denk ik dat het ideale gebruik niet is om gameverwerking uit te voeren wanneer OnXXXXXXXX wordt aangeroepen, maar om alleen de invoerinhoud te behouden en die waarden te gebruiken in de updateverwerking van het spel.

Trouwens, in de huidige staat wordt het niet aangeroepen wanneer de knop wordt losgelaten, dus het is niet mogelijk om te bepalen wanneer OnAttack de knop wordt losgelaten. Om hierop te reageren, selecteert u de aanvalsactie die de knop definieert in de instellingen van de actiekaart en voegt u "Druk" toe vanuit "Interacties". Stel daarna het triggergedrag van de toegevoegde pers in op "Press And Release" en sla het op.

Wanneer uitgevoerd, kunt u zien dat wordt aangeroepen, zelfs OnAttack wanneer de knop wordt losgelaten. isPressed false Omdat het wordt, is het ook mogelijk om te bepalen of het de timing van release is.

Overigens moet u deze interactie verwijderen omdat deze in de toekomst niet zal worden gebruikt.

Input ontvangen met Invoke Unity Events

Een tweede manier om input te ontvangen is Invoke Unity Events, dus laten we dit proberen. Zoals hierboven vermeld, kan het gebruik van meerdere invoermethoden conflicterende verwerking veroorzaken, dus als andere verwerking is ingeschakeld, schakelt u deze uit.

Plaats eerst het tekstobject zodat de invoerinformatie kan worden weergegeven.

Eenheidsgebeurtenissen aanroepen maakt een leeg object waarmee gerelateerde bewerkingen worden uitgevoerd.

Voeg Input > Player Input toe aan het lege object.

Stel het actiekaartbestand dat u hebt gemaakt voor Acties (in dit geval InputActionSample) in en stel de actiekaart die u hebt gemaakt (in dit geval SideScrollActionMap) in op Standaardtoewijzing. Stel gedrag in om eenheidsgebeurtenissen aan te roepen.

Maak een script. De naam is arbitrair, maar in dit geval InputInvokeUnityEvents is het .

Het script ziet er als volgt uit:

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

De methodenaam OnMoveOnAttack die wordt aangeroepen wanneer de gebruiker ermee communiceert, is , zoals in het geval van Berichten verzenden. In Eenheidsgebeurtenissen aanroepen kunt u deze methodenaam naar wens instellen.

Wanneer elk wordt aangeroepen, wordt het doorgegeven als een InputAction.CallbackContext argument, zodat u de invoerstatus vanaf daar kunt krijgen. Als u een "waarde" instelt in de actie, kunt u deze ontvangen in de methode en als u een "knop" insteltReadValueAsButton, kunt u ReadValue deze in de methode ontvangen.

Nadat u het script hebt opgeslagen, koppelt u de spelerinvoer aan het object dat u instelt en stelt u het weergavetekstobject in.

Vouw vervolgens "Event" en "Action Map Name (SideScrollActionMap)" uit in Player Input en je zou de acties "Move" en "Attack" moeten zien die je hebt gemaakt.

Klik eerst op de knop + op Verplaatsen om het toe te voegen.

Het object in de linkerbenedenhoek is uw eigen object en de functie is ingesteld op de methode die u zojuist hebt gemaakt OnMove .

Configureer ook de gebeurtenis Attack.

Voer het spel uit om te zien hoe het werkt.

In principe wordt het alleen aangeroepen wanneer dezelfde waarde als Berichten verzenden verandert, maar om de een of andere reden kan de methode twee keer tegelijkertijd worden aangeroepen. Ik weet de oorzaak niet, maar ik denk dat het waarschijnlijk komt omdat het startproces en het continue proces tegelijkertijd lopen. Ik denk echter dat er geen probleem is als je alleen de ingevoerde waarde behoudt zoals in het geval van Berichten verzenden en de daadwerkelijke spelverwerking afzonderlijk uitvoert in het updateproces.

Een automatisch gegenereerd script gebruiken om invoergegevens te ontvangen

In de derde sectie wordt beschreven hoe u invoerinformatie kunt verkrijgen met behulp van een script dat is gegenereerd op basis van een actiekaartbestand.

Aangezien er een mogelijkheid is van conflicten met andere acquisitieprocessen, moet u andere acquisitieprocessen uitschakelen.

Plaats een tekstobject om de invoergegevens weer te geven.

Maak ook een leeg object voor het ophalen van invoergegevens. In dit artikel wordt een automatisch gegenereerd script gebruikt, zodat u geen spelerinvoer hoeft toe te voegen.

Het script dat automatisch wordt gegenereerd op basis van de actiekaart is slechts een bibliotheek, dus maak een afzonderlijk besturingsscript. De naam is arbitrair, maar in dit geval InputScript is het .

Het script ziet er als volgt uit:

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

Definieer een automatisch gegenereerde klasse InputActionSample op basis van het actieoverzicht in het veld. Deze klasse definieert elke actieset in het actieoverzicht en u kunt de gebeurtenissen instellen die worden aangeroepen wanneer deze acties worden uitgevoerd.

Awake In de methode InputActionSample wordt een instantie van gemaakt en wordt de gebeurtenis die wordt aangeroepen op het moment van de actie ingesteld. Wanneer OnMoveu deze bewerkingen uitvoert, wordt de methode , OnAttack nu aangeroepen.

Omdat we hier echter alleen de gebeurtenis instellen, moeten we OnEnable de methode aanroepen wanneer Enable deze wordt aangeroepen om de actiekaart in te schakelen.

Omdat het invoergedrag van de gebruiker wordt behandeld als een globale bewerking, Om te voorkomen dat OnDisable de actiemap extra doet nadat dit object ongeldig is gemaakt, roepen we de methode in Disable de methode aan om het uit te schakelen.

Nadat u het script hebt opgeslagen, koppelt u het aan het lege object dat u hebt gemaakt en stelt u het tekstobject in voor weergave.

Voer het spel uit om te zien hoe het werkt.

Zoals u kunt zien, wordt de methode niet aangeroepen wanneer OnMove de bewerking Verplaatsen (0, 0) wordt. Ik weet niet zeker waarom, maar het lijkt erop dat de uitgevoerde gebeurtenis alleen degene neemt met toetsaanslagen ingeschakeld.

Trouwens, als je Interacties niet hebt ingesteld in de actiekaart voor Attack, wordt deze niet aangeroepen wanneer OnAttack je de knop loslaat.

Om dit af te canceled handelen, moet u een evenement instellen. Als u geen speciale verwerking wilt uitvoeren op (0, 0), kunt u de methode aanroepen zoals deze is OnMove . Hetzelfde geldt voor 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);   // 追加
}

Voer uit en controleer of Move:(0, 0) of Attack:False wordt weergegeven.