Bouw Arkanoid met eenheid speler en balmechanica

Wat je gaat creëren

In deze tutorialserie laten we u zien hoe u het klassieke Arkanoid (of Breakout) -spel in Unity kunt recreëren, met behulp van de eigen 2D-hulpmiddelen van Unity. In elke post zullen we ons concentreren op een specifiek deel van het spel; in dit bericht krijgen we de peddel en de bal in beweging.

Waar we gebleven zijn

In de vorige zelfstudie hebt u het project ingesteld, de items geïmporteerd en de scène voorbereid voor het eerste niveau. Als u de vorige zelfstudie niet hebt voltooid, raden we u sterk aan dit te doen voordat u deze start.

Laatste voorbeeld

Bekijk deze demo om te zien waar we naar streven in de hele serie:

En hier is wat we zullen hebben aan het einde van dit deel:

Speler beweging

Je hebt de paddle van de speler al in de interface; nu moet je ermee communiceren. Je zult het op een horizontale manier verplaatsen, links en rechts. Om die beweging door invoer te creëren, moet je een creëren Script.

Scripts zijn stukjes programmacode die specifieke taken uitvoeren. Unity kan drie programmeertalen aan: Boo, C # en JavaScript. Alle scripts die in deze zelfstudie zijn gemaakt, worden in C # geschreven (maar u kunt ze desgewenst in een andere taal implementeren).

 Ga naar uw account om een ​​script te maken project tab, selecteer de map scripts, en klik erop met de rechtermuisknop om een ​​menu te openen. kiezen Maak> C # Script aan. Een nieuw bestand genaamd NewBehaviourScript zal verschijnen; hernoem het naar PlayerScript. In de Inspecteur tab zie je de inhoud van het script zelf.

Dubbelklik op het script om het te bewerken. De MonoDevelop IDE wordt standaard geopend, maar u kunt een andere code-editor configureren om deze te openen als u dat wilt.

gebruikmakend van UnityEngine; met behulp van System.Collections; public class NewBehaviourScript: MonoBehaviour // Gebruik dit voor initialisatie ongeldig Start ()  // Update wordt eenmaal per frame ongeldig Update () 

Alle Unity-scripts hebben standaard twee methoden:

  • Begin(): gebruikt om alle variabelen of parameters die we nodig hebben in onze code te initialiseren.
  • Bijwerken(): noemde elk frame van het spel en werd dus gebruikt om de spelstatus bij te werken.

Om de speler te verplaatsen, hebt u twee stukjes informatie nodig:

  • speler positie
  • speler snelheid

Maak dus twee variabelen (globale klassevariabelen) om die informatie op te slaan:

openbare float playerVelocity; private Vector3 playerPosition;

Zoals je misschien hebt gemerkt, playerVelocity is een openbare variabele, terwijl speler positie is privé. Waarom hebben we dit gedaan? Met Unity kunt u de waarden van openbare variabelen in de editor wijzigen zonder dat u de feitelijke code hoeft te wijzigen; dit is erg handig als u parameters hebt die continu moeten worden aangepast. De snelheid is een van die gevallen, dus we maken het openbaar.

Sla het script op (in MonoDevelop) en ga opnieuw naar de Unity-editor.

Je hebt nu het script; je hoeft het alleen maar toe te wijzen aan het peddelobject van de speler. Selecteer de paddle uit de Hiërarchie tab en in de Inspecteur, Klik Component toevoegen. Typ nu de naam van het script dat u zojuist hebt opgeslagen en voeg het toe aan het spelobject.

Zie Unity: Now You're Thinking With Components voor meer informatie over het concept van componenten en hoe ze in Unity werken.

Een andere manier om het script aan het onderdeel toe te voegen, is door het uit de map te slepen en over het bestand te slepen Component toevoegen Gebied. Je zou zoiets in je moeten zien Inspecteur:

Zoals je kunt zien, sinds we de playerVelocity variabele public, kunt u nu de waarde ervan in de editor instellen. Stel de waarde nu in op 0.3 en keer terug naar de code.

U initialiseert nu de speler positie. Om dit te doen, moet je toegang krijgen tot de positie van het spelobject in de scripts Begin methode:

// Gebruik dit voor initialisatie ongeldig Start () // verkrijg de beginpositie van het spelobject playerPosition = gameObject.transform.position; 

Nu hebben we de paddle's gedefinieerd eerste positie en snelheid, maar we moeten het nog verplaatsen. Daarvoor zullen we de Bijwerken methode. 

Omdat we alleen bezwaar willen maken om horizontaal te bewegen, kunnen we de GetAxis methode van de Invoer klasse om te bepalen in welke richting de invoer van de speler langs de horizontale as wijst (-1 voor links, +1 voor rechts), vermenigvuldig deze waarde met de snelheid, voeg deze waarde toe aan de huidige X-positie van de paddle en update de huidige speler positie matchen.

Hoewel we te maken hebben met invoer, willen we er ook voor zorgen dat het spel wordt afgesloten wanneer de speler op Esc sleutel.

Het volledige fragment is hieronder:

gebruikmakend van UnityEngine; met behulp van System.Collections; publieke klasse PlayerScript: MonoBehaviour public float playerVelocity; private Vector3 playerPosition; // Gebruik dit voor initialisatie ongeldig Start () // verkrijg de beginpositie van het spelobject playerPosition = gameObject.transform.position;  // Update wordt eenmaal per frame ongeldig Update () // horizontale beweging playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // verlaat het spel als (Input.GetKeyDown (KeyCode.Escape)) Application.Quit ();  // update de game-objecttransformatie transform.position = playerPosition; 

Sla het script op en keer terug naar de Unity-editor. Druk nu op Spelen en probeer de speler met de linker- en rechterpijlen te verplaatsen.

Het spelgebied definiëren

U hebt waarschijnlijk gemerkt dat de paddle buiten het niveau kan bewegen. Dit gebeurt omdat er geen grenzen zijn gedefinieerd voor het gamegebied. 

Maak eerst een andere openbare variabele om de grens te maken - noem die grens.

Deze variabele slaat de maximale X-positie op waar de paddle naartoe kan bewegen. Omdat we het niveau in een symmetrische vorm om de positie gaan bouwen (0, 0, 0), dit betekent dat de absolute grenswaarde hetzelfde zal zijn voor zowel positieve als negatieve X.

Om te voorkomen dat de speler de grens overschrijdt, voegen we er een paar toe als voorwaarden. Kortom, we zullen zeggen dat als de x-waarde van de positie groter is dan de grenswaarde, de x-waarde gelijk is aan de grens. Op deze manier zorgen we ervoor dat de paddle het speelveld nooit kan verlaten. De relevante code is hieronder: 

gebruikmakend van UnityEngine; met behulp van System.Collections; publieke klasse PlayerScript: MonoBehaviour public float playerVelocity; private Vector3 playerPosition; openbare vlottergrens; // Gebruik dit voor initialisatie ongeldig Start () // verkrijg de beginpositie van het spelobject playerPosition = gameObject.transform.position;  // Update wordt eenmaal per frame ongeldig Update () // horizontale beweging playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // verlaat het spel als (Input.GetKeyDown (KeyCode.Escape)) Application.Quit ();  // update de game-objecttransformatie transform.position = playerPosition; // grenzen als (playerPosition.x < -boundary)  transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z);  if (playerPosition.x > boundary) transform.position = new Vector3 (boundary, playerPosition.y, playerPosition.z); 

Ga nu terug naar de editor en bereken de beste waarde voor de grens. Door de positie van de paddle op de X-as te slepen, kunt u zien dat de perfecte waarde is 5.46 (in ons project tenminste).

In de Inspecteur, reset de X-waarde van de paddelpositie naar 0, en invoer 5.46 op de Grens parameter onder de Spelerscript bestanddeel.

druk op Spelen in de editor. Nu kun je de paddle verplaatsen, maar alleen binnen het speelveld.

Fysieke eigenschappen maken

In dit specifieke spel moeten we fysieke eigenschappen creëren voor drie componenten: de paddle, de bal en de muren. Omdat we een 2D-game maken, zullen we 2D gebruiken en toepassen colliders. (Een collider is een bepaald type component waarmee de bijbehorende objecten op andere colliders kunnen reageren.)

Begin met het toevoegen van een collider aan onze paddle. In de Hiërarchie, selecteer ons paddle-object. Ga naar de Inspecteur, Klik Component toevoegen en typ collider. Zoals u in de onderstaande schermafbeelding kunt zien, zijn er verschillende soorten colliders beschikbaar die u kunt gebruiken. Elke individuele collider heeft specifieke eigenschappen die op het gerelateerde object lijken.

Omdat de speler een rechthoekformaat heeft, gebruiken we de Box Collider 2D. Selecteer het en de component wordt automatisch toegevoegd aan uw spelerobject. De waarden voor de grootte en de middenpositie van de collider zijn al gedefinieerd; deze standaardwaarden werken voor u, dus u hoeft ze niet te wijzigen.

Doe nu hetzelfde proces voor de drie balken en het blok. (Hiërarchie> Inspecteur> Component toevoegen> Box Collider 2D).

Al je game-objecten hebben nu botsers, verwacht de bal. Omdat de bal een andere vorm heeft, moet je een andere rijder gebruiken. Selecteer het en, in de Inspecteur tab, voeg het component toe Circle Collider 2D.

De Circle Collider 2D is vergelijkbaar met de Box Collider, behalve dat in plaats van de Grootte parameter die de breedte en hoogte van de box bepaalt, deze heeft een Radius parameter die de straal van de cirkel definieert.

Stuiterend materiaal

Om de bal te laten stuiteren, moeten we een stuiterend fysiek materiaal maken en dit aan de bal bevestigen. Unity heeft dat specifieke materiaal al gemaakt, dus we moeten het gewoon toevoegen. 

Op de project tab, maak een nieuwe map binnen de aanwinst map en noem deze Fysica. Selecteer deze map, klik creëren, en kies Physics2D-materiaal. Geef je nieuwe natuurkundig materiaal een naam BallPhysicsMaterial.

Het materiaal heeft twee parameters: Wrijving en springerigheid. Omdat je een zuiver bouncy-gedrag wilt, moet je de waarden dienovereenkomstig aanpassen: 0 voor Wrijving, 1 voor springerigheid.

Nu dat je het materiaal klaar hebt, pas het dan toe op de bal. Selecteer het balspelobject op de Hiërarchie tab en ga naar de Inspecteur. Als je de jouwe eens nader bekijkt Circle Collider 2D, u zult opmerken dat deze component een parameter heeft genaamd Materiaal; hier kun je elk fysiek materiaal dat je wilt bijvoegen.

Om de te bevestigen BallPhysicsMaterial, selecteer het en sleep het naar de Materiaal parameter op de collider.

Noot van de redacteur: deze schermafbeelding toont een Box Collider 2D, maar het zou een zijn Circle Collider 2D.

Een rigide lichaam toevoegen

Om de bal onder de controle van de natuurkunde te laten bewegen, moeten we nog een laatste ding toevoegen: een rigide component. Selecteer het balobject en voeg het onderdeel toe RigidBody 2D. Dit onderdeel heeft verschillende parameters die kunnen worden aangepast. Aangezien de bal alleen door stuiteren beweegt, moet je de Zwaartekracht schaal parameter van 1 naar 0-op deze manier zorgen we ervoor dat de bal niet wordt beïnvloed door de zwaartekracht. De rest van de parameters kan als standaard worden achtergelaten:

Het balobject programmeren

De bal zal volledig dynamisch zijn, dus we moeten een aangepast script voor dat gedrag maken. 

Maak een nieuw script (we zullen C # opnieuw gebruiken) en noem het BallScript. Ken dat nieuwe script toe aan het balobject (Hiërarchie> Inspecteur> Component toevoegen).

Laten we nu de regels en eigenschappen van de bal analyseren voordat ze in het script worden gecodeerd:

  • De bal moet twee toestanden hebben: inactief (volgt de paddle voordat het spel begint) en actief (kaatst af van de paddle, muren en blokken).
  • De bal wordt pas actief als de speler op een specifieke toets op het toetsenbord drukt.
  • Wanneer de bal actief wordt, oefenen we er kracht op uit om hem te laten bewegen.
  • Als de bal van het scherm valt, moet deze worden gereset.

Op basis van die informatie zullen we eerst de globale variabelen creëren ballIsActive, ballPosition, en ballInitialForce.

privé bool ballIsActive; privé Vector3 ballPosition; privé Vector2 ballInitialForce;

Nu de variabelen zijn ingesteld, moet u het game-object initialiseren. In de Begin methode, zou u:

  • Creëer een kracht om de bal te duwen.
  • Zet de bal op inactief.
  • Bewaar de balpositie.

Zo ziet het eruit:

void Start () // create the force ballInitialForce = new Vector2 (100.0f, 300.0f); // ingesteld op inactieve ballIsActive = false; // ballpositie ballPosition = transform.position; 

Hier passen we een kracht van toe 300 langs de Y-as om de bal naar boven te laten bewegen, en 100 langs de X-as om de bal diagonaal te laten bewegen in plaats van direct omhoog. Op deze manier dwing je de speler om de peddelpositie te verplaatsen.

In de Bijwerken methode, we zullen het gedrag van de bal bepalen. Laten we dit van geval tot geval bekijken.

Eerst moeten we de gebruikersinvoer afhandelen; we zullen de standaard gebruiken Springen knop van Unity as en actieknop. De sleutel die is gekoppeld aan Springen kan worden gewijzigd, maar de standaard is de Ruimte balk op het toetsenbord.

void Update () // controleer voor gebruikersinvoer if (Input.GetButtonDown ("Jump") == true) 

Het volgende dat u moet doen, is de balstatus controleren, omdat de actieknop alleen moet werken als de bal inactief is:

void Update () // check voor gebruikersinvoer if (Input.GetButtonDown ("Jump") == true) // controleer of is de eerste keer spelen als (! ballIsActive) 

Laten we aannemen dat dit aan het begin van het spel is, dus we moeten een kracht op de bal uitoefenen en deze actief maken. De nieuwe Bijwerken methode moet er als volgt uitzien:

void Update () // check voor gebruikersinvoer if (Input.GetButtonDown ("Jump") == true) // controleer of is de eerste play als (! ballIsActive) // een force rigidbody2D.AddForce toevoegt (ballInitialForce ); // set ball active ballIsActive =! ballIsActive; 

Nu, Spelen uw project en test de Springen actie; je zult zien dat de bal wordt opgestuwd en begint rond te stuiteren zoals het hoort. Je zult echter ook opmerken dat de bal de positie van de paddle niet volgt wanneer hij niet actief is. Stop het spel en laten we dat veranderen.

In de Bijwerken methode, moeten we de balstatus controleren en, als de bal inactief is, moeten we ervoor zorgen dat de X-waarde van de bal dezelfde is als de X-waarde van de peddel. 

Ah, maar hoe kunnen we toegang krijgen tot de positie van de speler als deze zich in een ander game-object bevindt? Simpel: we maken gewoon een spelobjectvariabele en slaan hierin een verwijzing op naar het paddle-object. Voeg dus het paddle-object toe als een openbare globale variabele van het type GameObject:

privé bool ballIsActive; privé Vector3 ballPosition; privé Vector2 ballInitialForce; // GameObject public GameObject playerObject;

Terug naar de Bijwerken methode. We zullen de baltoestand controleren en de paddle-referentie. Als de status inactief is en het peddelobject niet nul is (dat wil zeggen, we hebben er een verwijzing naar), moet de bal de positie van de paddle volgen. Het complete Bijwerken is nu:

void Update () // check voor gebruikersinvoer if (Input.GetButtonDown ("Jump") == true) // controleer of is de eerste play als (! ballIsActive) // een force rigidbody2D.AddForce toevoegt (ballInitialForce ); // set ball active ballIsActive =! ballIsActive;  if (! ballIsActive && playerObject! = null) // verkrijg en gebruik de positie van de speler ballPosition.x = playerObject.transform.position.x; // pas speler X-positie op de bal toe transform.position = ballPosition; 

Sla je script op en ga terug naar de editor. Zoals je misschien al gemerkt hebt, is de paddle-referentie openbaar, wat betekent dat je het doorgeeft aan de editor. Op de Hiërarchie tab, selecteer de bal. In de Inspecteur, je zult de Player-object parameter in ons script is momenteel Geen.

Om dit een verwijzing naar het player paddle-game-object te maken, sleept en sleept u eenvoudig het paddle-game-object vanuit de Hiërarchie naar de Player-object parameter in het script.

Klik op de Spelen knop, en test je spel. Je zult nu zien dat de bal de speler zal volgen vóór de Springen toets is ingedrukt.

Het spel opnieuw instellen

Er is nog één ding dat u moet doen om het script te voltooien. Zoals je misschien hebt gemerkt, als de speler de bal niet vangt, valt deze uit de set en wordt de game niet opnieuw ingesteld. Laten we het aanpassen Bijwerken methode om dat te verhelpen. 

We zullen controleren of de bal actief is en of de Y-positie kleiner is dan -6. Als dat zo is, stellen we de bal inactief en wordt de balpositie teruggezet naar de spelerpositie. Het fragment voor dat ziet er zo uit:

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

Als u het script opslaat en de editor controleert, kunt u zien dat telkens wanneer de bal van het scherm valt, de positie van de bal wordt verplaatst naar de spelerpositie en op inactief wordt gezet. Als je echter begint te spelen, merk je een vreemd gedrag Elke keer dat de bal valt, neemt de snelheid van de volgende keer dat je op de actietoets drukt toe. Waarom is dat? 

Wel, onthoud dat we een kracht toevoegen aan de bal wanneer deze wordt gelanceerd, dus elke keer dat je het spel reset, blijf je kracht toevoegen aan het stijve lichaam, waardoor het spel waanzinnig moeilijk wordt na een paar pogingen. Dus de vraag is, hoe lossen we dit op?

Om dezelfde algehele kracht te behouden, moeten we ervoor zorgen dat u alle krachten verwijdert die op de bal zijn toegepast, elke keer dat u de bal reset. Om dit te doen, kunnen we eenvoudig de Is Kinematic parameter elke keer dat de bal stopt, en deactiveer deze wanneer het spel start. Deze parameter bepaalt of de bal al dan niet wordt beïnvloed door de fysica en het uitschakelen ervan zorgt ervoor dat alle eerder toegepaste krachten zullen verdwijnen. 

Voeg nog twee regels toe aan uw Bijwerken methode om dit te doen:

  • rigidbody2D.isKinematic = false voordat de kracht wordt toegevoegd, en
  • rigidbody2D.isKinematic = true wanneer we willen dat de bal weer begint te bewegen.

Op het einde, de complete Bijwerken methode zou er als volgt uit moeten zien:

public class BallScript: MonoBehaviour private bool ballIsActive; privé Vector3 ballPosition; privé Vector2 ballInitialForce; // GameObject public GameObject playerObject; // Gebruik dit voor initialisatie ongeldig Start () // create the force ballInitialForce = new Vector2 (100.0f, 300.0f); // ingesteld op inactieve ballIsActive = false; // ballpositie ballPosition = transform.position;  // Update wordt eenmaal per frame ongeldig Update () // controleer voor gebruikersinvoer if (Input.GetButtonDown ("Jump") == true) // controleer of de eerste play is als (! BallIsActive) / / reset de force rigidbody2D.isKinematic = false; // voeg een force rigidbody2D.AddForce toe (ballInitialForce); // set ball active ballIsActive =! ballIsActive;  if (! ballIsActive && playerObject! = null) // verkrijg en gebruik de positie van de speler ballPosition.x = playerObject.transform.position.x; // pas speler X-positie op de bal toe transform.position = ballPosition;  // Controleer of de bal valt als (ballIsActive && transform.position.y < -6)  ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true;   

Nu kan je Spelen het spel en verifieert alle voornoemde geïmplementeerde functies.

De volgende keer

Dit is het tweede deel van de serie. U hebt nu aangepaste scripts, fysica-colliders en geprogrammeerde gebruikersinvoer geïmplementeerd. De volgende keer zullen we de blokken instellen.

Als u vragen of feedback heeft over wat we tot nu toe hebben behandeld, laat dan hieronder een reactie achter.