#3 Space Invaders - Creiamo il nostro esercito di Invaders - Unity Tutorial
Come promesso nel precedente articolo, in questo andremo a scrivere lo script per disporre gli invasori sulla scena, animare ogni singolo invader e farli muovere. Ma non perdiamoci in chiacchiere, andiamo a creare il nostro esercito!
Invader
Dalla cartella Assets, creiamo una nuova cartella chiamata Script. All'interno di essa, creiamo un nuovo script in C# e lo chiamiamo Invader
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
public class Invader : MonoBehaviour
{
public SpriteRenderer spriteRenderer { get; private set; }
public Sprite[] animationSprites = new Sprite[0];
public float animationTime = 1f;
public int animationFrame { get; private set; }
public int score = 10;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
spriteRenderer.sprite = animationSprites[0];
}
private void Start()
{
InvokeRepeating(nameof(AnimateSprite), animationTime, animationTime);
}
private void AnimateSprite()
{
animationFrame++;
// Loop back to the start if the animation frame exceeds the length
if (animationFrame >= animationSprites.Length) {
animationFrame = 0;
}
spriteRenderer.sprite = animationSprites[animationFrame];
}
}
Ecco il significato del codice appena scritto:
- La variabile spriteRenderer: rappresenta il componente SpriteRenderer associato all'invader.
- L'array animationSprites: definisce un array di sprite che contiene gli sprite da utilizzare per l'animazione dell'invader.
- La variabile animationTime: definisce il tempo in secondi tra ogni frame dell'animazione dell'invader.
- La variabile animationFrame: rappresenta il frame corrente dell'animazione dell'invader.
- La variabile score: definisce il punteggio assegnato al giocatore quando viene eliminato l'invader.
- Il metodo Awake(): indica che il metodo seguente verrà chiamato durante l'inizio del ciclo di vita dell'invader. Al suo interno valorizziamo la variabile spriteRenderer con il componente SpriteRenderer associato all'invader e successivamente impostiamo il primo frame dell'animazione come sprite iniziale.
- Il metodo Start(): verrà chiamato durante la fase di "Start" dell'invader, ovvero alla fine del suo ciclo di vita. All'interno di esso, invochiamo ripetutamente il metodo "AnimateSprite" ogni "animationTime" espressi in secondi.
- Il metodo AnimateSprite(): il metodo che viene chiamato per animare lo sprite dell'invader. Al suo interno, incrementiamo il frame corrente dell'animazione e, se l'incremento supera l'ultimo frame dell'animazione, riparte dall'inizio. Infine settiamo lo sprite dell'invader in base al frame corrente dell'animazione.
Una volta creato e spiegato lo script, lo associamo ai nostri prefab invader creati in precedenza. Per farlo, dobbiamo aggiungere lo script al prefab Invader_Base, che verrà automaticamente aggiunto alle varianti che abbiamo creato. Per associare lo script, selezioniamo il prefab Invader_Base e trasciniamo lo script nello spazio vuoto della sezione Inspector. Una volta fatto ciò, selezioniamo gli altri prefab creati, noteremo che tutti hanno lo script associato.
Per ogni variante creata, iniziamo ad associare i corretti sprites. Ad esempio, selezioniamo Invader_01 e impostiamo 2 come valore alla voce Animation Sprites. Noteremo che sono stati creati due Element. Dalla cartella Sprites, associamo al primo Element Invader_01-1.png e al secondo Invader_01-2.png. Ripetiamo la stessa operazione per Invader_02 e Invader_03, associando loro gli sprites corretti. Se vogliamo vedere il risultato, trasciniamo gli invader sulla scena e clicchiamo Play
L'esercito di invaders
Una volta animati gli invader, possiamo finalmente creare la nostra griglia di invader. Quindi, creiamo un nuovo script e chiamiamolo Invaders.
using UnityEngine;
public class Invaders : MonoBehaviour
{
[Header("Invaders")]
public Invader[] prefabs = new Invader[5];
public float speed = 1f;
public Vector3 direction { get; private set; } = Vector3.right;
public Vector3 initialPosition { get; private set; }
[Header("Grid")]
public int rows = 5;
public int columns = 11;
private void Awake()
{
// Form the grid of invaders
for (int i = 0; i < rows; i++)
{
float width = 2f * (columns - 1);
float height = 2f * (rows - 1);
Vector2 centerOffset = new Vector2(-width * 0.5f, -height * 0.5f);
Vector3 rowPosition = new Vector3(centerOffset.x, (2f * i) + centerOffset.y, 0f);
for (int j = 0; j < columns; j++)
{
// Create an invader and parent it to this transform
Invader invader = Instantiate(prefabs[i], transform);
// Calculate and set the position of the invader in the row
Vector3 position = rowPosition;
position.x += 2f * j;
invader.transform.localPosition = position;
}
}
}
private void Update()
{
this.transform.position += direction * speed * Time.deltaTime;
// Transform the viewport to world coordinates so we can check when the
// invaders reach the edge of the screen
Vector3 leftEdge = Camera.main.ViewportToWorldPoint(Vector3.zero);
Vector3 rightEdge = Camera.main.ViewportToWorldPoint(Vector3.right);
// The invaders will advance to the next row after reaching the edge of
// the screen
foreach (Transform invader in transform)
{
// Skip any invaders that have been killed
if (!invader.gameObject.activeInHierarchy) {
continue;
}
// Check the left edge or right edge based on the current direction
if (direction == Vector3.right && invader.position.x >= (rightEdge.x - 1f))
{
AdvanceRow();
break;
}
else if (direction == Vector3.left && invader.position.x <= (leftEdge.x + 1f))
{
AdvanceRow();
break;
}
}
}
private void AdvanceRow()
{
// Flip the direction the invaders are moving
direction = new Vector3(-direction.x, 0f, 0f);
// Move the entire grid of invaders down a row
Vector3 position = transform.position;
position.y -= 1f;
transform.position = position;
}
}
Ecco il significato del codice appena scritto:
- Il gioco ha diverse variabili pubbliche che possono essere regolate a piacimento. Ad esempio, è possibile specificare il numero di righe e colonne della griglia degli invader, la velocità di movimento e gli oggetti di invasori prefabbricati che saranno utilizzati per creare gli invader.
- Il metodo Awake() inizializza la griglia degli invader posizionandoli uniformemente sulla schermata. Per fare ciò, il metodo utilizza due cicli for annidati per posizionare ogni invader nella griglia.
- Il metodo Update() si occupa del movimento degli invader. In particolare, sposta tutti gli invader verso sinistra o destra in base alla direzione corrente (inizialmente verso destra). Se un invader raggiunge il bordo destro o sinistro dello schermo, chiama il metodo AdvanceRow().
- Il metodo AdvanceRow() cambia la direzione del movimento degli invader, da destra a sinistra o viceversa, e sposta l'intera griglia di una riga verso il basso.
Una volta finito lo script, aggiungiamolo alla scena. Creiamo un Empty GameObject, chiamiamolo Invaders e aggiungiamogli lo script appena creato. Successivamente settiamo la sua Position Y a 7 e andiamo i prefab degli invader allo script. Possiamo scegliere l'ordine a nostro piacimento. Per vedere il risultato, possiamo avviare la scena cliccando su Play.
Conclusione
Per oggi la concludiamo qui, abbiamo creato gli invader e la griglia di gioco che si muoveva verso destra e sinistra, implementando una parte fondamentale del gameplay del nostro gioco. Nel prossimo articolo ci concentreremo sulla creazione del player e dei proiettili, completando così il nucleo del gioco. Restate sintonizzati per ulteriori aggiornamenti sul nostro progetto! Parte 4
Commenti
Posta un commento