In questa serie di tutorial, ti mostreremo come ricreare il classico gioco Arkanoid (o Breakout) in Unity, utilizzando gli strumenti 2D nativi di Unity. In ogni post, ci concentreremo su una parte specifica del gioco; in questo post, otterremo la pagaia e la palla in movimento.
Nel tutorial precedente, hai impostato il progetto, importato le risorse e preparato la scena per il primo livello. Se non hai completato il tutorial precedente, ti consigliamo vivamente di farlo prima di iniziare questo.
Dai un'occhiata a questa demo per vedere a cosa miriamo per l'intera serie:
Ed ecco cosa avremo alla fine di questa parte:
Hai già la paletta del giocatore nell'interfaccia; ora devi interagire con esso. Lo sposterai orizzontalmente, a sinistra ea destra. Per creare quel movimento per input, devi creare un copione.
Gli script sono frammenti di codice di programmazione che svolgono compiti specifici. Unity può gestire tre linguaggi di programmazione: Boo, C # e JavaScript. Tutti gli script creati in questo tutorial saranno scritti in C # (ma si senta libero di implementarli in un'altra lingua se preferisci).
Per creare uno script, vai al tuo Progetto scheda, selezionare la cartella Script, e fare clic con il tasto destro per visualizzare un menu. Selezionare Crea> Script C #. Un nuovo file chiamato NewBehaviourScript
apparirà; rinominalo in PlayerScript
. Nel Ispettore scheda vedrai il contenuto dello script stesso.
Fare doppio clic sullo script per modificarlo. L'IDE di MonoDevelop si aprirà di default, ma se lo preferisci puoi configurare un altro editor di codice per aprirlo.
usando UnityEngine; usando System.Collections; public class NewBehaviourScript: MonoBehaviour // Utilizza questo per l'inizializzazione void Start () // L'aggiornamento viene chiamato una volta per frame void Update ()
Tutti gli script Unity avranno due metodi predefiniti:
Inizio()
: utilizzato per inizializzare qualsiasi variabile o parametro di cui abbiamo bisogno nel nostro codice.Aggiornare()
: chiamato ogni singolo frame del gioco, e quindi usato per aggiornare lo stato del gioco.Per spostare il giocatore, hai bisogno di due informazioni:
Pertanto, creare due variabili (variabili di classe globali) per memorizzare tali informazioni:
player float pubblicoVelocity; privato Vector3 playerPosition;
Come avrai notato, playerVelocity
è una variabile pubblica, mentre Posizione del giocatore
è privato. Perché lo abbiamo fatto? Bene, Unity consente di modificare i valori delle variabili pubbliche all'interno dell'editor senza la necessità di modificare il codice effettivo; questo è molto utile quando si hanno parametri che devono essere regolati continuamente. La velocità è uno di quei casi, quindi lo rendiamo pubblico.
Salvare lo script (in MonoDevelop) e spostarsi nuovamente sull'editor Unity.
Ora hai la sceneggiatura; devi solo assegnarlo all'oggetto paddle del giocatore. Seleziona la pagaia da Gerarchia scheda e in Ispettore, clic Aggiungi componente. Ora digita il nome dello script che hai appena salvato e aggiungilo all'oggetto del gioco.
Per ulteriori informazioni sul concetto di Componenti e su come funzionano in Unity, vedere Unity: Now You're Thinking With Components.
Un altro modo per aggiungere lo script al componente sarebbe trascinarlo dalla sua cartella e rilasciarlo sul Aggiungi componente la zona. Dovresti vedere qualcosa di simile nel tuo Ispettore:
Come puoi vedere, da quando abbiamo lasciato il playerVelocity
variabile pubblica, ora puoi impostare il suo valore nell'editor. Per ora, imposta il valore su 0.3
e tornare al codice.
Ora inizializzerà il Posizione del giocatore
. Per fare ciò, devi accedere alla posizione dell'oggetto del gioco nello script Inizio
metodo:
// Usa questo per l'inizializzazione void Start () // ottieni la posizione iniziale dell'oggetto di gioco playerPosition = gameObject.transform.position;
Ora abbiamo definito la pagaia iniziale posizione e velocità, ma dobbiamo ancora spostarlo. Per questo, modificheremo il Aggiornare
metodo.
Dal momento che vogliamo solo obiettare di spostarci orizzontalmente, possiamo usare il GetAxis
metodo del Ingresso
classe per trovare in quale direzione l'input del giocatore punta lungo l'asse orizzontale (-1
per sinistra, +1
per destra), moltiplica questo valore per la velocità, aggiungi questo valore alla posizione X corrente della pala e aggiorna la corrente Posizione del giocatore
abbinare.
Mentre abbiamo a che fare con l'input, vogliamo anche assicurarci che il gioco esca quando il giocatore preme il tasto Esc chiave.
Lo snippet completo è qui sotto:
usando UnityEngine; usando System.Collections; public class PlayerScript: MonoBehaviour public float playerVelocity; privato Vector3 playerPosition; // Usa questo per l'inizializzazione void Start () // ottieni la posizione iniziale dell'oggetto di gioco playerPosition = gameObject.transform.position; // L'aggiornamento viene chiamato una volta per frame void Update () // movimento orizzontale playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // lascia il gioco se (Input.GetKeyDown (KeyCode.Escape)) Application.Quit (); // aggiorna l'oggetto del gioco transform transform.position = playerPosition;
Salva lo script e torna all'editor Unity. Ora premi Giocare e prova a muovere il giocatore con le frecce sinistra e destra.
Probabilmente hai notato che la paletta può spostarsi fuori dal livello. Questo accade perché non ci sono limiti definiti per l'area di gioco.
Per creare il confine, prima crea un'altra variabile pubblica, chiamala confine
.
Questa variabile memorizzerà la posizione X massima a cui la paletta può spostarsi. Dal momento che stiamo andando a costruire il livello in una forma simmetrica attorno alla posizione (0, 0, 0)
, questo significa che il valore del confine assoluto sarà lo stesso sia per la X positiva che per quella negativa.
Per evitare che il giocatore superi il confine, aggiungeremo un paio di Se
condizioni. Fondamentalmente, diremo che se il valore x della posizione è maggiore del valore limite, il valore x verrà impostato uguale al limite. In questo modo, ci assicuriamo che la pagaia non possa mai lasciare l'area di gioco. Il codice rilevante è di seguito:
usando UnityEngine; usando System.Collections; public class PlayerScript: MonoBehaviour public float playerVelocity; privato Vector3 playerPosition; limite di galleggiamento pubblico; // Usa questo per l'inizializzazione void Start () // ottieni la posizione iniziale dell'oggetto di gioco playerPosition = gameObject.transform.position; // L'aggiornamento viene chiamato una volta per frame void Update () // movimento orizzontale playerPosition.x + = Input.GetAxis ("Horizontal") * playerVelocity; // lascia il gioco se (Input.GetKeyDown (KeyCode.Escape)) Application.Quit (); // aggiorna l'oggetto del gioco transform transform.position = playerPosition; // boundaries if (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);
Ora, torna all'editor e trova il miglior valore per il confine
. Trascinando la posizione della pala sull'asse X, puoi vedere che il valore perfetto è 5.46
(almeno nel nostro progetto).
Nel Ispettore, resettare il valore X della posizione della pala a 0
, e input 5.46
sul Confine parametro sotto il Script del giocatore componente.
stampa Giocare nell'editor. Ora puoi spostare la pagaia, ma solo all'interno dell'area di gioco.
In questo particolare gioco, abbiamo bisogno di creare proprietà fisiche per tre componenti: la pagaia, la palla e le pareti. Dal momento che stiamo creando un gioco 2D, useremo e applicheremo 2D collider. (Un collider è un particolare tipo di componente che consente agli oggetti associati di reagire agli altri collider).
Inizia aggiungendo un collisore alla nostra pagaia. Nel Gerarchia, seleziona il nostro oggetto paddle. Sposta in Ispettore, clic Aggiungi componente e scrivi Collider
. Come puoi vedere nello screenshot qui sotto, diversi tipi di collisori sono disponibili per l'uso. Ogni singolo collisore ha proprietà specifiche che assomigliano all'oggetto correlato.
Dal momento che il giocatore ha un formato rettangolare, useremo il Box Collider 2D. Selezionalo e il componente verrà automaticamente aggiunto al tuo oggetto giocatore. I valori per la dimensione e la posizione centrale del collisore sono già definiti; questi valori predefiniti funzioneranno per te, quindi non è necessario cambiarli.
Ora, fai lo stesso processo per le tre barre e il blocco. (Gerarchia> Impostazioni> Aggiungi componente> Collimatore 2D).
Tutti i tuoi oggetti di gioco ora hanno i collisori, aspettati la palla. Dato che la palla ha una forma diversa, dovrai usare un collisore diverso. Selezionalo e, nel Ispettore scheda, aggiungi il componente Circle Collider 2D.
Il Circle Collider 2D è simile al Box Collider, tranne che al posto del Taglia parametro che definisce la larghezza e l'altezza della scatola, ha a Raggio parametro che definisce il raggio del cerchio.
Per far rimbalzare la palla, dobbiamo creare un rimbalzo del materiale fisico e attaccarlo alla palla. Unity ha già creato quel materiale specifico, quindi abbiamo solo bisogno di aggiungerlo.
Sul Progetto scheda, creare una nuova cartella all'interno del Bene cartella e chiamarlo Fisica
. Seleziona questa cartella, clicca Creare, e scegliere Materiale Physics2D. Dai un nome al tuo nuovo materiale di fisica BallPhysicsMaterial
.
Il materiale ha due parametri: Attrito e bounciness. Dal momento che si desidera un comportamento bouncy puro, è necessario modificare i valori di conseguenza: 0
per Attrito, 1
per bounciness.
Ora che hai preparato il materiale, applicalo alla palla. Seleziona l'oggetto del gioco della palla sul Gerarchia scheda e passare al Ispettore. Se dai un'occhiata più da vicino al tuo Circle Collider 2D, noterai che questo componente ha un parametro chiamato Materiale; qui puoi allegare qualsiasi materiale fisico che desideri a quell'oggetto.
Per allegare il BallPhysicsMaterial, basta selezionarlo e trascinarlo sul Materiale parametro sul collisore.
Nota del redattore: questa schermata mostra a Box Collider 2D, ma dovrebbe essere un Circle Collider 2D.Affinché la palla possa muoversi sotto il controllo della fisica, dobbiamo aggiungere un'ultima cosa: una componente di un corpo rigido. Seleziona l'oggetto palla e aggiungi il componente RigidBody 2D. Questo componente ha diversi parametri che possono essere regolati. Poiché la palla si muoverà solo rimbalzando, dovresti cambiare il Scala di gravità parametro da 1
a 0
-in questo modo, ci assicuriamo che la palla non sia influenzata dalla gravità. Il resto dei parametri può essere lasciato come predefinito:
La palla sarà completamente dinamica, quindi abbiamo bisogno di creare uno script personalizzato per quel comportamento.
Crea un nuovo script (useremo di nuovo C #) e nominalo BallScript
. Assegna quel nuovo script all'oggetto palla (Gerarchia> Impostazioni> Aggiungi componente).
Ora, analizziamo le regole e le proprietà della palla, prima di codificarle nella sceneggiatura:
Sulla base di tali informazioni, prima creeremo le variabili globali ballIsActive
, ballPosition
, e ballInitialForce
.
private bool ballIsActive; Vector3 ballPosition privato; private Vector2 ballInitialForce;
Ora che hai impostato le variabili, devi inizializzare l'oggetto del gioco. Nel Inizio
metodo, dovresti:
Ecco come appare:
void Start () // crea la forza ballInitialForce = new Vector2 (100.0f, 300.0f); // impostato su inattivo ballIsActive = false; // ball position ballPosition = transform.position;
Qui, applichiamo una forza di 300
lungo l'asse Y per far muovere la palla verso l'alto, e 100
lungo l'asse X per far muovere la palla in diagonale anziché direttamente verso l'alto. In questo modo, costringi il giocatore a spostare la posizione della pagaia.
Nel Aggiornare
metodo, definiremo il comportamento della palla. Approcciamo caso per caso.
Innanzitutto, dobbiamo gestire l'input dell'utente; useremo il default Saltare
pulsante di Unity as e tasto azione. La chiave associata a Saltare
può essere cambiato, ma il default è il Spazio barra sulla tastiera.
void Update () // verifica l'input dell'utente se (Input.GetButtonDown ("Jump") == true)
La prossima cosa da fare è controllare lo stato della palla, poiché il tasto azione dovrebbe funzionare solo quando la palla è inattiva:
void Update () // verifica l'input dell'utente if (Input.GetButtonDown ("Jump") == true) // controlla se è la prima esecuzione se (! ballIsActive)
Supponiamo che questo sia all'inizio del gioco, quindi dobbiamo applicare una forza alla palla e renderla attiva. Il nuovo Aggiornare
il metodo dovrebbe assomigliare a:
void Update () // verifica l'input dell'utente if (Input.GetButtonDown ("Jump") == true) // verifica se è la prima riproduzione se (! ballIsActive) // aggiungi una forza rigidbody2D.AddForce (ballInitialForce ); // set ball active ballIsActive =! ballIsActive;
Adesso, Giocare il tuo progetto e prova il Saltare
azione; noterai che la palla viene sollevata e inizia a rimbalzare come dovrebbe. Tuttavia, noterai anche che la palla non segue la posizione della pagaia quando è inattiva. Ferma il gioco e cambiamo.
Nel Aggiornare
metodo, dobbiamo controllare lo stato della palla e, se la palla è inattiva, dobbiamo assicurarci che il valore X della palla sia lo stesso del valore X della pagaia.
Ah, ma come possiamo accedere alla posizione del giocatore se si trova in un altro oggetto di gioco? Semplice: creiamo semplicemente una variabile oggetto di gioco e memorizziamo un riferimento all'oggetto paddle al suo interno. Quindi, aggiungi l'oggetto paddle come variabile globale pubblica di tipo GameObject
:
private bool ballIsActive; Vector3 ballPosition privato; private Vector2 ballInitialForce; // GameObject public GameObject playerObject;
Ritorno al Aggiornare
metodo. Controlleremo lo stato della palla e il riferimento della pagaia. Se lo stato è inattivo e l'oggetto paddle non è nullo (cioè, abbiamo un riferimento ad esso), la palla dovrebbe seguire la posizione della pagaia. Il completo Aggiornare
è ora:
void Update () // verifica l'input dell'utente if (Input.GetButtonDown ("Jump") == true) // verifica se è la prima riproduzione se (! ballIsActive) // aggiungi una forza rigidbody2D.AddForce (ballInitialForce ); // set ball active ballIsActive =! ballIsActive; if (! ballIsActive && playerObject! = null) // ottieni e usa la posizione del giocatore ballPosition.x = playerObject.transform.position.x; // applica la posizione del giocatore X alla palla transform.position = ballPosition;
Salva il tuo script e torna all'editor. Come avrai notato, il riferimento alla paddle è pubblico, il che significa che lo passerai sull'editor. Sul Gerarchia scheda, selezionare la palla. Nel Ispettore, noterai il Oggetto del giocatore il parametro nel nostro script è attualmente Nessuna
.
Per fare di questo un riferimento all'oggetto del gioco paddle del giocatore, basta trascinare e rilasciare l'oggetto del gioco paddle dal Gerarchia al Oggetto del giocatore parametro nello script.
Clicca il Giocare pulsante e prova il tuo gioco. Ora vedrai che la palla seguirà il giocatore prima del Saltare
il tasto è premuto.
C'è solo un'altra cosa che devi fare per finire lo script. Come avrai notato, se il giocatore non prende la palla, cadrà dal set e il gioco non si resetterà. Modifichiamo il Aggiornare
metodo per risolverlo.
Controlleremo se la palla è attiva e se la sua posizione Y è inferiore a -6
. Se è così, metteremo la palla inattiva e ripristineremo la posizione della palla nella posizione del giocatore. Lo snippet per questo assomiglia a questo:
if (ballIsActive && transform.position.y < -6) ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition;
Se salvi lo script e controlli l'editor, puoi vedere che ogni volta che la palla cade dallo schermo, la posizione della palla viene riposizionata nella posizione del giocatore e impostata su inattiva. Tuttavia, se inizi a giocare noterai uno strano comportamento Ogni volta che la palla cade, la prossima volta che premi il tasto azione la sua velocità aumenta. Perché?
Bene, ricorda che aggiungiamo una forza alla palla quando si lancia, quindi, ogni volta che resetti il gioco, continui ad aggiungere forza al corpo rigido, rendendo il gioco follemente difficile solo dopo alcuni tentativi. Quindi, la domanda è, come possiamo risolvere questo?
Per mantenere la stessa forza generale applicata, dobbiamo assicurarci di eliminare tutte le forze applicate alla palla ogni volta che la resetti. Per fare ciò, possiamo semplicemente attivare il È cinematico
parametro ogni volta che si ferma la palla, e disattivarla quando inizia il gioco. Questo parametro determina se la palla è influenzata o meno dalla fisica, e disabilitandola farà in modo che tutte le forze applicate prima scompaiano.
Aggiungi altre due linee al tuo Aggiornare
metodo per fare questo:
rigidbody2D.isKinematic = false
prima che la forza venga aggiunta, erigidbody2D.isKinematic = true
quando vogliamo che la palla ricomincia a muoversi.Alla fine, il completo Aggiornare
il metodo dovrebbe assomigliare a questo:
BallScript di classe pubblica: MonoBehaviour private bool ballIsActive; Vector3 ballPosition privato; private Vector2 ballInitialForce; // GameObject public GameObject playerObject; // Usa questo per l'inizializzazione void Start () // crea la forza ballInitialForce = new Vector2 (100.0f, 300.0f); // impostato su inattivo ballIsActive = false; // ball position ballPosition = transform.position; // L'aggiornamento viene chiamato una volta per frame void Update () // verifica l'input dell'utente if (Input.GetButtonDown ("Jump") == true) // controlla se è la prima riproduzione se (! BallIsActive) / / resetta la forza rigidbody2D.isKinematic = false; // aggiungi una forza rigidbody2D.AddForce (ballInitialForce); // set ball active ballIsActive =! ballIsActive; if (! ballIsActive && playerObject! = null) // ottieni e usa la posizione del giocatore ballPosition.x = playerObject.transform.position.x; // applica la posizione del giocatore X alla palla transform.position = ballPosition; // Controlla se la palla cade se (ballIsActive && transform.position.y < -6) ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true;
Ora puoi Giocare il gioco e verificare tutte le funzionalità implementate in precedenza.
Questo conclude la seconda parte della serie. Ora hai implementato script personalizzati, collisori fisici e input utente programmato. La prossima volta, imposteremo i blocchi.
Se hai domande o commenti su ciò che abbiamo trattato finora, ti preghiamo di lasciare un commento qui sotto.