Bygg Arkanoid Med Enhet Spiller og Ball Mekanikk

Hva du skal skape

I denne opplæringsserien vil vi vise deg hvordan du gjenskaper det klassiske Arkanoid-spillet (eller Breakout) i Unity, ved hjelp av Unitys innfødte 2D-verktøy. I hvert innlegg fokuserer vi på en bestemt del av spillet; I dette innlegget får vi padle og ballen beveger seg.

Hvor vi forlot

I den forrige opplæringen satte du opp prosjektet, importerte eiendelene og forberedte scenen på første nivå. Hvis du ikke har fullført den tidligere opplæringen, anbefaler vi deg sterkt å gjøre det før du starter denne.

Endelig forhåndsvisning

Ta en titt på denne demonstrasjonen for å se hva vi sikter mot i hele serien:

Og her er hva vi får på slutten av denne delen:

Spillerbevegelse

Du har allerede spillerens padle i grensesnittet; nå må du samhandle med den. Du vil flytte den på en horisontal måte, til venstre og høyre. For å skape den bevegelsen ved å skrive inn, må du opprette en Manus.

Skript er utdrag av programmeringskode som gjør bestemte oppgaver. Enhet kan håndtere tre programmeringsspråk: Boo, C #, og JavaScript. Alle skript opprettet i denne opplæringen vil bli skrevet i C # (men vær så snill å implementere dem på et annet språk hvis du foretrekker det).

 For å lage et skript, gå til din Prosjekt kategorien, velg mappen scripts, og høyreklikk det for å åpne en meny. Å velge Opprett> C # Script. En ny fil som heter NewBehaviourScript vil dukke opp; omdøpe den til PlayerScript. I Inspektør fanen vil du se innholdet i selve skriptet.

Dobbeltklikk på skriptet for å redigere det. MonoDevelop IDE åpnes som standard, men du kan konfigurere en annen kodeditor for å åpne den hvis du foretrekker det.

bruker UnityEngine; bruker System.Collections; offentlig klasse NewBehaviourScript: MonoBehaviour // Bruk dette for initialisering tomt Start ()  // Oppdatering kalles en gang per ramme ugyldig Oppdatering () 

Alle Unity-skript vil ha to metoder som standard:

  • Start(): brukes til å initialisere eventuelle variabler eller parametere som vi trenger i vår kode.
  • Oppdater(): kalt hver enkelt ramme i spillet, og så pleide å oppdatere spilltilstanden.

For å flytte spilleren trenger du to deler av informasjonen:

  • spiller posisjon
  • spillerhastighet

Dermed opprett to variabler (globale klassevariabler) for å lagre denne informasjonen:

offentlig float playerVelocity; privat Vector3 playerPosition;

Som du kanskje har lagt merke til, playerVelocity er en offentlig variabel, mens playerPosition er privat. Hvorfor gjorde vi dette? Vel, Unity tillater deg å endre verdiene av offentlige variabler inne i editoren uten å måtte endre den faktiske koden; Dette er veldig nyttig når du har parametere som må kontinuerlig justeres. Hastigheten er et av de tilfellene, så vi gjør det offentlig.

Lagre skriptet (i MonoDevelop) og flytt til Unity-editoren igjen.

Du har nå skriptet; du trenger bare å tildele det til spillerens padleobjekt. Velg padle fra hierarki fanen og i Inspektør, klikk Legg til komponent. Skriv inn navnet på skriptet du nettopp har lagret, og legg det til spillobjektet.

For mer informasjon om begrepet Komponenter og hvordan de fungerer i Enhet, se Enhet: Nå tenker du på komponenter.

En annen måte å legge til skriptet på komponenten ville være å dra det fra mappen og slippe det over Legg til komponent område. Du bør se noe sånt i din Inspektør:

Som du kan se, siden vi forlot playerVelocity variabel offentlig, kan du nå sette verdien i redigeringen. For nå, sett verdien til 0.3 og gå tilbake til koden.

Du vil nå initialisere playerPosition. For å gjøre dette må du få tilgang til spillobjektets posisjon i skriptets Start metode:

// Bruk dette for initialisering tomt Start () // få startposisjonen til spillobjektet playerPosition = gameObject.transform.position; 

Nå har vi definert padleens første posisjon og hastighet, men vi må fortsatt flytte den. For det vil vi redigere Oppdater metode. 

Siden vi bare ønsker å protestere mot å bevege seg horisontalt, kan vi bruke GetAxis metode av Input klassen for å finne hvilken retning spillerens inngang peker langs horisontalaksen (-1 for venstre, +1 for høyre), multipliser denne verdien med hastigheten, legg til denne verdien til padleens nåværende X-posisjon, og oppdater gjeldende playerPosition å passe.

Mens vi har å gjøre med innspill, vil vi også sørge for at spillet går ut når spilleren trykker på Esc nøkkel.

Den komplette delen er under:

bruker UnityEngine; bruker System.Collections; offentlig klasse PlayerScript: MonoBehaviour public float playerVelocity; privat Vector3 playerPosition; // Bruk dette for initialisering tomt Start () // få startposisjonen til spillobjektet playerPosition = gameObject.transform.position;  // Oppdatering kalles en gang per ramme ugyldig Oppdatering () // horisontal bevegelse playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // la spillet hvis (Input.GetKeyDown (KeyCode.Escape)) Application.Quit ();  // oppdater spillobjektet transform transform.position = playerPosition; 

Lagre skriptet og gå tilbake til Unity-editoren. Trykk nå Spille og prøv å flytte spilleren med venstre og høyre pilene.

Definere spillområdet

Du har sikkert lagt merke til at padlen kan bevege seg utenfor nivået. Dette skjer fordi det ikke er definert grenser for spillområdet. 

For å opprette grensen, må du først opprette en annen offentlig variabel - ring den grense.

Denne variabelen lagrer den maksimale X-posisjonen som padlen kan flytte til. Siden vi skal bygge nivået i en symmetrisk form rundt posisjonen (0, 0, 0), Dette betyr at absolutt grenseverdien vil være den samme for både positiv og negativ X.

For å unngå at spilleren krysser grensen, legger vi til et par hvis forhold. I utgangspunktet vil vi si at hvis x-verdien av posisjonen er større enn grenseverdien, blir x-verdien satt lik grensen. På denne måten sikrer vi at padlen aldri kan forlate spillområdet. Den aktuelle koden er under: 

bruker UnityEngine; bruker System.Collections; offentlig klasse PlayerScript: MonoBehaviour public float playerVelocity; privat Vector3 playerPosition; offentlig flyte grense; // Bruk dette for initialisering tomt Start () // få startposisjonen til spillobjektet playerPosition = gameObject.transform.position;  // Oppdatering kalles en gang per ramme ugyldig Oppdatering () // horisontal bevegelse playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // la spillet hvis (Input.GetKeyDown (KeyCode.Escape)) Application.Quit ();  // oppdater spillobjektet transform transform.position = playerPosition; // grenser hvis (playerPosition.x < -boundary)  transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z);  if (playerPosition.x > grense) transform.position = ny Vector3 (grense, playerPosition.y, playerPosition.z); 

Nå, gå tilbake til redaktøren og trene den beste verdien for grense. Ved å dra padleposisjonen på X-aksen, kan du se at den perfekte verdien er 5,46 (i vårt prosjekt minst).

I Inspektør, tilbakestill X-verdien til padleposisjonen til 0, og innspill 5,46 på Grense parameter under Spillerskript komponent.

trykk Spille i redaktøren. Nå kan du flytte padle, men bare innenfor spillområdet.

Opprette fysiske egenskaper

I dette spesielle spillet må vi lage fysiske egenskaper for tre komponenter: padle, ballen og veggene. Siden vi lager et 2D-spill, bruker vi og bruker 2D colliders. (En collider er en bestemt type komponent som gjør at de tilhørende gjenstandene kan reagere på andre colliders.)

Start med å legge til en collider til vår padle. I hierarki, velg vårt padleobjekt. Flytt til Inspektør, klikk Legg til komponent og skriv inn Collider. Som du ser på skjermbildet under, er det flere typer colliders tilgjengelig for deg å bruke. Hver enkelt collider har spesifikke egenskaper som ligner det relaterte objektet.

Siden spilleren har et rektangelformat, bruker vi Box Collider 2D. Velg den, og komponenten blir automatisk lagt til spillerobjektet ditt. Verdiene for størrelsen og senterposisjonen til collider er allerede definert; Disse standardverdiene vil fungere for deg, slik at du ikke trenger å endre dem.

Gjør den samme prosessen for de tre stolpene og blokken. (Hierarki> Inspektør> Legg til komponent> Box Collider 2D).

Alle spillobjektene dine har nå kolliderer, forventer ballen. Siden ballen har en annen form, må du bruke en annen collider. Velg den og, i Inspektør fanen, legg til komponenten Circle Collider 2D.

De Circle Collider 2D ligner på Box Collider, bortsett fra at i stedet for Størrelse parameter som definerer boksenes bredde og høyde, den har a Radius parameter som definerer radius av sirkelen.

Bouncing Material

For å få ballen til å hoppe, må vi lage et hoppende fysisk materiale og feste det til ballen. Enhet har allerede laget det spesifikke materialet, så vi trenger bare å legge til det. 

Prosjekt kategorien, lag en ny mappe inne i ressurs mappe og navn den fysikk. Velg denne mappen, klikk Skape, og velg Fysikk2D Materiale. Gi det nye fysikkmaterialet ditt navn BallPhysicsMaterial.

Materialet har to parametere: Friksjon og bounciness. Siden du vil ha en ren hoppende oppførsel, må du endre verdiene tilsvarende: 0 til Friksjon, 1 til bounciness.

Nå som du har materialet klart, legg det på ballen. Velg ballspillobjektet på hierarki fanen og flytte til Inspektør. Hvis du ser nærmere på din Circle Collider 2D, Du vil legge merke til at denne komponenten har en parameter som heter Materiale; Her kan du feste fysisk materiale du vil ha den objekten.

For å legge ved BallPhysicsMaterial, bare velg det og dra det til Materiale parameter på collider.

Redaktørens notat: Dette skjermbildet viser en Box Collider 2D, men det skal være en Circle Collider 2D.

Legge til en stiv kropp

For at ballen skal bevege seg under fysikkens kontroll, må vi legge til en siste ting: en stivkomponent. Velg ballobjektet og legg til komponenten RigidBody 2D. Denne komponenten har flere parametere som kan justeres. Siden ballen bare beveger seg ved å hoppe, bør du endre Gravity Scale parameter fra 1 til 0-På den måten sikrer vi at ballen ikke påvirkes av tyngdekraften. Resten av parameterne kan stå som standard:

Programmering av ballobjektet

Kulen vil være helt dynamisk, så vi må opprette et tilpasset skript for atferden. 

Opprett et nytt skript (vi bruker C # igjen) og nevner det BallScript. Tilordne det nye skriptet til ballobjektet (Hierarki> Inspektør> Legg til komponent).

Nå kan vi analysere reglene og egenskapene til ballen før de kodes inn i skriptet:

  • Ballen skal ha to tilstander: uvirksom (følger padle før spillet begynner) og aktiv (spretter av padle, vegger og blokker).
  • Ballen blir bare aktiv når spilleren skyver en bestemt tast på tastaturet.
  • Når ballen blir aktiv, bruker vi en kraft til å begynne å bevege seg.
  • Hvis ballen faller av skjermen, bør den nullstilles.

Basert på den informasjonen, vil vi først opprette de globale variablene ballIsActive, ballPosition, og ballInitialForce.

privat bool ballIsActive; privat Vector3 ballposisjon; privat Vector2 ballInitialForce;

Nå som du har variablene satt, bør du initialisere spillobjektet. I Start metode, bør du:

  • Lag en kraft for å presse ballen.
  • Sett ballen til inaktiv.
  • Lagre ballposisjonen.

Slik ser det ut:

void Start () // lager kraften BallInitialForce = ny Vector2 (100.0f, 300.0f); // sett til inaktiv ballIsActive = false; // ball posisjon ballPosition = transform.position; 

Her bruker vi en kraft av 300 langs Y-aksen for å få ballen til å bevege seg oppover, og 100 langs X-aksen for å få ballen til å bevege seg diagonalt i stedet for direkte oppover. På denne måten tvinger du spilleren til å bevege padleposisjonen.

I Oppdater Metode, vi vil definere ballens oppførsel La oss nærme oss hvert enkelt tilfelle.

Først må vi håndtere brukerinngangene; Vi vil bruke standard Hoppe knapp for enhet som og handlingstast. Nøkkelen knyttet til Hoppe kan endres, men standard er Rom bar på tastaturet.

ugyldig oppdatering () // sjekk for brukerinngang hvis (Input.GetButtonDown ("Jump") == sann) 

Den neste tingen å gjøre er å kontrollere balltilstanden, siden handlingsnøkkelen bare skal fungere når ballen er inaktiv:

ugyldig oppdatering () // sjekk for brukerinngang hvis (Input.GetButtonDown ("Jump") == sann) // se om det er det første spillet hvis (! ballIsActive) 

La oss anta at dette er i starten av spillet, så vi må bruke en kraft til ballen og sette den aktiv. Den nye Oppdater metoden skal se ut som:

ugyldig oppdatering () // sjekk for brukerinngang hvis (Input.GetButtonDown ("Jump") == true) // sjekk om er det første spillet hvis (! ballIsActive) // legg til en kraft rigidbody2D.AddForce (ballInitialForce ); // sett ball aktiv ballIsActive =! ballIsActive; 

Nå, Spille prosjektet ditt og test på Hoppe handling; du vil legge merke til at ballen blir presset opp og begynner å hoppe rundt akkurat som det skal. Men du vil også merke at ballen ikke følger padleposisjonen rundt når den er inaktiv. Stopp spillet og la oss endre det.

I Oppdater Metode, vi må sjekke balltilstanden og, hvis ballen er inaktiv, må vi sørge for at X-verdien av ballen er den samme som padleens X-verdi. 

Åh, men hvordan kan vi få tilgang til spillerposisjonen hvis den er i et annet spillobjekt? Enkelt: Vi lager bare en variabel for spillobjekter og lagrer en referanse til padleobjektet i den. Så legg til padleobjektet som en offentlig global variabel av typen GameObject:

privat bool ballIsActive; privat Vector3 ballposisjon; privat Vector2 ballInitialForce; // GameObject offentlig GameObject playerObject;

Tilbake til Oppdater metode. Vi vil sjekke balltilstanden og padle referansen. Hvis staten er inaktiv og padleobjektet ikke er null (det vil si, vi har en referanse til det), bør ballen følge padleposisjonen. Den komplette Oppdater er nå:

ugyldig oppdatering () // sjekk for brukerinngang hvis (Input.GetButtonDown ("Jump") == true) // sjekk om er det første spillet hvis (! ballIsActive) // legg til en kraft rigidbody2D.AddForce (ballInitialForce ); // sett ball aktiv ballIsActive =! ballIsActive;  hvis (! ballIsActive && playerObject! = null) // få og bruk spilleren posisjon ballPosition.x = playerObject.transform.position.x; // søk spilleren X posisjon til ballen transform.position = ballPosition; 

Lagre skriptet ditt og gå tilbake til redigeringsprogrammet. Som du kanskje har lagt merke til, er padle referansen offentlig, noe som betyr at du vil passere den på redaktøren. På hierarki tab, velg ballen. I Inspektør, du vil legge merke til Spillerobjekt parameteren i vårt skript er for øyeblikket Ingen.

For å gjøre dette til en referanse til spillingsspillet, må du bare dra og slippe padle spillobjektet fra hierarki til Spillerobjekt parameter i skriptet.

Klikk på Spille knappen, og test spillet ditt. Du vil nå se at ballen vil følge spilleren før Hoppe tasten er trykket.

Tilbakestille spillet

Det er bare en ting du må gjøre for å fullføre skriptet. Som du kanskje har lagt merke til, hvis spilleren ikke tar ballen, faller den fra settet og spillet vil ikke nullstilles. La oss endre Oppdater metode for å fikse det. 

Vi kontrollerer om ballen er aktiv, og hvis Y-posisjonen er mindre enn -6. I så fall stiller vi ballen til inaktiv og tilbakestiller ballen til spilleren. Utdraget for det ser slik ut:

hvis (ballIsActive && transform.position.y < -6)  ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; 

Hvis du lagrer skriptet og sjekker redigereren, kan du se at hver gang ballen faller fra skjermen, plasseres ballenposisjonen til spilleren og stilles til inaktiv. Men hvis du begynner å spille vil du legge merke til en merkelig oppførsel Hver gang ballen faller, øker hastigheten neste gang du trykker på handlingstasten. Hvorfor det? 

Vel, kom ihåg at vi legger til en kraft til ballen når den starter - så hver gang du tilbakestiller spillet, fortsetter du å legge kraft til den stive kroppen, noe som gjør spillet uhyggelig hardt like etter noen få forsøk. Så spørsmålet er, hvordan løser vi dette?

For å opprettholde den samme overordnede kraften må vi sørge for at du fjerner alle krefter som brukes på ballen hver gang du tilbakestiller den. For å gjøre dette kan vi bare aktivere Er kinematisk parameter hver gang ballen stopper, og deaktiver den når spillet starter. Denne parameteren bestemmer hvorvidt ballen påvirkes av fysikk, og deaktivering av det vil sørge for at alle krefter som påføres før, forsvinner. 

Legg til to flere linjer til din Oppdater metode for å gjøre dette:

  • rigidbody2D.isKinematisk = false før kraften legges til, og
  • rigidbody2D.isKinematisk = sant når vi vil at ballen skal begynne å bevege seg igjen.

Til slutt, den komplette Oppdater metoden skal se slik ut:

offentlig klasse BallScript: MonoBehaviour private bool ballIsActive; privat Vector3 ballposisjon; privat Vector2 ballInitialForce; // GameObject offentlig GameObject playerObject; // Bruk dette for initialisering tomt Start () // opprett kraften ballInitialForce = ny Vector2 (100.0f, 300.0f); // sett til inaktiv ballIsActive = false; // ball posisjon ballPosition = transform.position;  // Oppdatering kalles en gang per ramme ugyldig Oppdatering () // sjekk for brukerinngang hvis (Input.GetButtonDown ("Jump") == true) // se om det er det første spillet hvis (! BallIsActive) / / tilbakestill kraften rigidbody2D.isKinematisk = false; // legg til en kraft rigidbody2D.AddForce (ballInitialForce); // sett ball aktiv ballIsActive =! ballIsActive;  hvis (! ballIsActive && playerObject! = null) // få og bruk spilleren posisjon ballPosition.x = playerObject.transform.position.x; // søk spilleren X posisjon til ballen transform.position = ballPosition;  // Sjekk om ballen faller hvis (ballIsActive && transform.position.y < -6)  ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true;   

Nå kan du Spille Spillet og verifiser alle de ovenfor nevnte implementerte funksjonene.

Neste gang

Dette avslutter den andre delen av serien. Du har nå implementert egendefinerte skript, fysikkskollider og programmert brukerinngang. Neste gang skal vi sette opp blokkene.

Hvis du har spørsmål eller tilbakemelding på hva vi har dekket så langt, vennligst legg igjen en kommentar nedenfor.