Brug handlingskort til at tildele knapper til spiladfærd

Side opdateret :
Dato for oprettelse af side :

Miljø til bekræftelse

Windows
  • Windows 11
Enhedslistens redaktør
  • 2020.3.25f1
Input System Pakke
  • 1.2.0

Forudsætninger for dette tip

Følgende indstillinger er foretaget på forhånd som en forudsætning for beskrivelsen af dette tip.

Om handlingskort

Brugerinputprogrammer på tastaturer, mus og gamepads sagde grundlæggende, at en bestemt handling blev udført, når der blev trykket på en knap. I handlingskortet kan du for eksempel definere handlingen med at "hoppe" og tildele controllerknapper og tastaturtaster til den. Som følge heraf behøver programmet kun at beskrive processen, når en bestemt handling udføres. Selvom du tildeler en knap på en anden controller som en eftertanke, kan du anvende den uden at ændre operativsystemet.

Oprettelse af en handlingsoversigt

Her vil jeg gerne oprette et handlingskort og vise brugerens inputoplysninger i teksten. Du kan få brugerinput ved hjælp af handlingsoversigter på flere måder.

Højreklik på en mappe i projektet for at oprette en inputhandling. Placeringen af den mappe, der skal oprettes, er vilkårlig, men administrer den i henhold til dit projekt. Filnavnet er også vilkårligt, men her InputActionSample er det .

Når du dobbeltklikker på den oprettede fil, vises følgende vindue.

Klik først på knappen + i Handlingskort for at oprette en handlingsoversigt. Hvis indholdet af handlingen ændres afhængigt af scenen, defineres det som en oprettelsesenhed i den pågældende enhed. For eksempel, i tilfælde af et siderullende actionspil, ændres indholdet af operationen under handlingen og i menuen, så du opretter et handlingskort for hver.

Her definerer vi som et eksempel en siderullende handling og navngiver den "SideScrollActionMap".

Opret derefter handlinger. Da det er en prøve, vil jeg ikke lave mange af dem, men her vil vi oprette "Flyt" handlinger til bevægelse og "Angreb" til angreb. Da der allerede er oprettet en, skal du ændre navnet eller oprette et nyt, klikke på + knappen i øverste højre hjørne og indtaste den.

Konfigurer først Move-konfigurationen. Controlleren antager, at du bruger styrepinden, D-blokken og tastaturpiletasterne. I tilfælde af en siderullende handling er der tilfælde, hvor kun venstre og højre bruges, men her antager vi, at du bruger fire retninger i betragtning af at hoppe med den øverste tast og sidde på hug med ned-tasten.

Når du vælger Flyt, er der et valg af handlingstype til højre, så indstil dette til "Værdi".

Du vil se kontroltypen nedenfor, så vælg Vector2. Dette skyldes, at toppen og bunden er tildelt Y, og venstre og højre er tildelt X.

Vælg derefter den nøgle, du vil tildele denne begivenhed. Vælg Ingen binding i midten, og vælg Sti til højre. Her vælger vi GamePad LeftStick.

Dette binder gamepadens venstre pind til bevægelsen.

For også at binde andre controllere skal du vælge "Tilføj binding" fra + knappen til højre for Flyt.

Nu hvor Ingen binding er tilføjet, tildeler vi en Dpad til GamePad.

På denne måde kan du tilføje den type controller, du vil understøtte, samt tasterne og pindene. Det er også muligt at indstille det specifikt til en bestemt spilkonsol.

Sticks og Dpads er knapper, der antager op, ned, venstre og højre, så de kan tilføjes med dette, men i tilfælde af tastaturer er de alle enkelttaster, så der er ingen definition for op, ned, venstre og højre. Hvis du vil indstille tastaturet op, ned, til venstre eller højre, skal du vælge Tilføj op ned venstre højre sammensat fra knappen +.

En 2D-vektor tilføjes derefter, og du kan tildele den til hver op ned venstre højre, som vist i nedenstående figur.

Hvis du f.eks. bruger Op, skal du indstille "Pil op" på tastaturet. Forresten, hvis du er besværlig at finde en nøgle, kan du nemt vælge den ved at trykke på måltasten, mens du klikker på knappen "Lyt".

Op er nu indstillet til Pil op.

På samme måde skal du indstille Down, Left og Right, og du er færdig.

Selvfølgelig kan ikke kun piletaster, men også WASD indstilles.

Konfigurer derefter Attack. Attack er let at tildele, fordi det er en enkelt knap. Vælg først Angreb, og sørg for, at handlingstypen er en knap.

Vælg derefter Ingen binding, og vælg den knap, du vil tildele, fra stien.

Hvis du vil tilføje flere, skal du vælge "Tilføj binding" fra + knappen.

Tilføj så mange, som du har brug for. Da det behandles som en knap, kan tastaturet indstilles på samme måde som en spilcontroller.

Når alle indstillinger er færdige, skal du klikke på "Gem aktiv" for at gemme. Du kan lukke dette vindue.

Endelig skal du med projektets inputactions-fil (i dette tilfælde den InputActionSample-fil, du oprettede tidligere), markere "Generer C # Class" i inspektøren. Parameteren tilføjes, men klik på knappen "Anvend" som den er.

Dette genererer en scriptfil med samme navn. Den indeholder klasser, der er nyttige til brug af handlingskort fra programmer.

Sådan modtager du inputoplysninger

Der er flere måder at modtage input baseret på et handlingskort. Dette tip forklarer tre mønstre, men det er bedre at fokusere på et af dem, når du rent faktisk laver et spil. Hvis du bruger dem separat, vil det være besværligt at administrere.

Hvis du bruger flere metoder til modtagelse af input i en enkelt scene, kan behandlingen også være i konflikt internt og ikke fungere korrekt.

Modtage inputoplysninger i Send meddelelser

Den første metode her er, hvordan man modtager inputoplysninger i "Send meddelelser".

Denne gang vil jeg vise de indtastede oplysninger i teksten, så jeg placerer et tekstobjekt.

Da dette tip også vil forsøge at få flere inputoplysninger, opretter vi et tomt objekt for at indstille komponenten separat. Navnet kan være hvad som helst.

Føj derefter en Player Input-komponent til det tomme objekt. Player Input er en vigtig komponent til at forbinde handlingskort og scripts.

I "Tilføj komponent" er der "Player Input" i kategorien "Input", så tilføj den.

Når komponenten Spillerinput er tilføjet, skal du indstille det handlingskort, du oprettede i "Handlinger". Slip det fra projektet, eller vælg det fra + ikonet til højre.

Kontroller, at standardkortet er det, du oprettede i handlingsoversigten.

Kontroller, at adfærden er "Send meddelelser".

Opret derefter et script. Filnavnet kan være hvad som helst, men her InputSendMessage er det .

Scriptet ser sådan ud:

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}";
  }
}
  • Objektet har et afspillerinput vedhæftet, der indstiller Send meddelelser
  • Arv fra MonoBehaviour

Hvis betingelserne er opfyldt, så hvis du definerer en metode kaldet "OnXXXXXXXX", Målmetoden kaldes, når den angivne handlingsoperation udføres. "XXXXXXXX" er navnet på de handlinger, der er oprettet i handlingsoversigten. Her har vi oprettet "Flyt" og "Angrib" handlinger, så metodenavnene er henholdsvis "OnMove" og "OnAttack".

OnMove Du kan få det indtastede beløb fra argumentet InputValue om . Da kontroltypen er indstillet til "Vector 2", modtages inputværdien InputValue.Get<Vector2> i .

OnAttackInputValue.isPressed Du kan få, om du også trykker ind.

Når du har gemt scriptet, skal du vedhæfte det til et objekt, der har komponenten Afspillerinput. Indstil også tekstobjektet til visning.

Kør spillet og tag et kig. Denne gang har jeg inkluderet definitionen af gamepad og tastatur, så det skal fungere, uanset hvilken du betjener.

Som du kan se, når du flytter den, kan du se, at metoden kun kaldes, når der er en ændring i værdien fra den tidligere tilstand. For eksempel, mens du flytter pinden til venstre, kaldes den målrettet, men ikke til venstre (- OnMove 1,0). OnMove Angrebsknappen reagerer også kun i det øjeblik, den trykkes, og hvis den trykkes og holdes, kaldes metoden ikke.

Derfor tror jeg, at den ideelle brug ikke er at udføre spilbehandling, når OnXXXXXXXX kaldes, men kun at beholde inputindholdet og bruge disse værdier i spillets opdateringsbehandling.

Forresten, i den aktuelle tilstand kaldes det ikke, når knappen frigives, så det er ikke muligt at bestemme, hvornår OnAttack knappen frigives. For at reagere på dette skal du vælge den angrebshandling, der definerer knappen i handlingskortindstillingerne, og tilføje "Tryk på" fra "Interaktioner". Derefter skal du indstille udløseradfærden for den tilføjede presse til "Tryk og frigiv" og gem den.

Når den udføres, kan du se, at den kaldes, selv OnAttack når knappen slippes. isPressed false Da det bliver , er det også muligt at afgøre, om det er tidspunktet for frigivelse.

Forresten, slet venligst denne interaktion, fordi den ikke vil blive brugt i fremtiden.

Modtag input med Invoke Unity Events

En anden måde at modtage input på er Invoke Unity Events, så lad os prøve dette. Som nævnt ovenfor kan brug af flere inputmetoder forårsage modstridende behandling, så hvis anden behandling er aktiveret, skal du deaktivere den.

Placer først tekstobjektet, så inputoplysningerne kan vises.

Invoke Unity Events opretter et tomt objekt, der udfører relaterede handlinger.

Føj input > afspillerinput til det tomme objekt.

Angiv den handlingstilknytningsfil, du oprettede for Handlinger (i dette tilfælde InputActionSample), og angiv den handlingsafbildning, du oprettede (i dette tilfælde SideScrollActionMap), til Standardtilknytning. Indstil funktionsmåde for at aktivere enhedshændelser.

Opret et script. Navnet er vilkårligt, men i dette tilfælde InputInvokeUnityEvents er det .

Scriptet ser sådan ud:

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

MetodenavnetOnMoveOnAttack, der kaldes, når brugeren interagerer med det, er , som i tilfældet med Send meddelelser. I Invoke Unity Events kan du indstille dette metodenavn, som du vil.

Når hver kaldes, sendes den som et InputAction.CallbackContext argument, så du kan få inputstatus derfra. Hvis du indstiller en "værdi" i handlingen, kan du modtage den i metoden, og hvis du indstiller ReadValueAsButton en "knap", kan du ReadValue modtage den i metoden.

Når du har gemt scriptet, skal du vedhæfte afspillerinput til det objekt, du indstiller, og indstille displaytekstobjektet.

Udvid derefter "Event" og "Action Map Name (SideScrollActionMap)" i Player Input, og du bør se handlingerne "Flyt" og "Angreb", du oprettede.

Klik først på knappen + på Flyt for at tilføje den.

Objektet i nederste venstre hjørne er dit eget objekt, og funktionen er indstillet til den metode, du lige har oprettet OnMove .

Konfigurer også hændelsen Attack.

Kør spillet for at se, hvordan det fungerer.

Dybest set kaldes det kun, når den samme værdi som Send meddelelser ændres, men af en eller anden grund kan metoden kaldes to gange på samme tid. Jeg kender ikke årsagen, men jeg tror, det nok skyldes, at startprocessen og den kontinuerlige proces kører på samme tid. Jeg tror dog, at der ikke er noget problem, hvis du kun beholder den indtastede værdi som i tilfældet med Send beskeder og udfører den faktiske spilbehandling separat i opdateringsprocessen.

Brug et automatisk genereret script til at modtage inputoplysninger

I tredje afsnit beskrives, hvordan du får inputoplysninger ved hjælp af et script, der er genereret fra en handlingstilknytningsfil.

Da der er mulighed for konflikter med andre anskaffelsesprocesser, skal du deaktivere andre anskaffelsesprocesser.

Placer et tekstobjekt for at få vist inputoplysningerne.

Opret også et tomt objekt til hentning af inputoplysninger. Denne artikel bruger et automatisk genereret script, så du behøver ikke at tilføje afspillerinput.

Det script, der automatisk genereres fra handlingsoversigten, er kun et bibliotek, så opret et separat kontrolscript. Navnet er vilkårligt, men i dette tilfælde InputScript er det .

Scriptet ser sådan ud:

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

Definer en automatisk genereret klasse InputActionSample ud fra handlingsoversigten i marken. Denne klasse definerer hvert handlingssæt i handlingsoversigten, og du kan angive de hændelser, der kaldes, når disse handlinger udføres.

Awake I metoden oprettes en forekomst af, og den begivenhed, der kaldes på tidspunktet for handlingen, InputActionSample indstilles. Når OnMovedu udfører disse handlinger, kaldes metoden , OnAttack nu.

Men da vi kun indstiller begivenheden her, skal vi OnEnable kalde metoden, når Enable den kaldes for at aktivere handlingskortet.

Da brugerens inputadfærd behandles som en global operation, For at forhindre OnDisable , at handlingskortet gør ekstra, efter at dette objekt er ugyldigt, kalder vi metoden i Disable metoden for at deaktivere den.

Når du har gemt scriptet, skal du vedhæfte det til det tomme objekt, du oprettede, og indstille tekstobjektet til visning.

Kør spillet for at se, hvordan det fungerer.

Som du kan se, kaldes metoden ikke, når OnMove Move-operationen bliver (0, 0). Jeg er ikke sikker på hvorfor, men det ser ud til, at den udførte begivenhed faktisk kun tager den med tastetryk aktiveret.

Forresten, hvis du ikke har indstillet interaktioner i handlingskortet for angreb, kaldes det ikke, når OnAttack du slipper knappen.

For at canceled håndtere dette skal du oprette en begivenhed. Hvis du ikke vil udføre speciel behandling ved (0, 0), kan du kalde metoden som den er OnMove . Det samme gælder for 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);   // 追加
}

Kør og kontroller, at Flyt:(0, 0) eller Angreb:Falsk vises.