Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Nemici, collisioni e punti vita

Generare i nemici, impostare il laser per colpirli, contare i punti esperienza e la vita del giocatore, aumentare il livello di gioco.
Generare i nemici, impostare il laser per colpirli, contare i punti esperienza e la vita del giocatore, aumentare il livello di gioco.
Link copiato negli appunti

In questa lezione continuiamo il lavoro sul gioco che abbiamo iniziato nella lezione precedente (che possiamo scaricare da qui), introdurremo i nemici e armeremo il nostro personaggio con un laser e lavoreremo con le collisioni per vederli morire ed esplordere.

Creare il GameObject dei nemici

Iniziamo realizzando il GameObject dei nemici e lo faremo seguendo lo stesso procedimento utilizzato per il personaggio del giocatore avremo un GameObject principale e le diverse animazioni gestite da un semplice script.

Creiamo quindi subito un GameObject vuoto (GameObject > Create Empty), lo chiamiamo "Enemy" e ne fissiamo la posizione a (0, 0, 0).

Fatto questo cerchiamo la texture del ragno col cilindro (Spider) nella cartella Textures/Enemy e impostiamo il relativo sprite. Clicchiamo sull'immagine e impostiamo nella finestra Inspector la proprietà Sprite Mode su multiple e Pixel To Units a 93 e clicchiamo su "Apply"

Ora creiamo i GameObject per i tre stati e animazioni del ragno: selezioniamo tutti e tre i fotogrammi che formano la camminata (Spider_2, Spider_3 e Spider_4) e li trasciniamo sulla scena.

Unity creerà per noi una animazione, che possiamo chiamare "spider_walk.anim". L'animazione sarà associata ad un nuovo GameObject, che chiameremo SpiderWalk. Facciamo lo stesso per il fotogramma degli altri due stati (morto, col GameObject chiamato SpiderDead e fermo con GameObject SpiderIdle ).

Selezioniamo i tre nuovi GameObject e li trasciniamo sotto l'oggetto Enemy nella finestra Hierarchy, poi mantenendoli tutti selezionati diamo a tutti e tre la posizione (0, 0, 0) nella finestra inspector.

Ora possiamo collegare lo script per la gestione delle animazioni dei personaggi anche ai nemici. Per farlo trasciniamo su Enemy lo script "AnimationHandler" che troviamo nella cartella Scripts.

Lo script viene aggiunto come componente e non ci resta che assegnare e tre animazioni del ragno alle proprietà public che vengono esposte. Quindi trasciniamo i GameObject sulle relative variabili. Come azione di default impostiamo Animation State a 0 (la camminata).

Il comportamento dei nemici

Il passo successivo è quello di definire come dovranno essere generati i nemici quale sarà il loro comportamento nel gioco. Diciamo di volerli creare fuori dal campo d'azione e farli spostare verso sinistra fino a trovarceli davanti.

Creiamo quindi un nuovo script nella cartella Scripts e lo chiamiamo EnemyHandler. Lo trasciniamo subito sull'oggetto Enemy nella finestra Hierarchy, per assegnarlo al nostro ragno, e lo modifichiamo con Visual Studio:

using UnityEngine;
using System.Collections;
public class EnemyHandler : MonoBehaviour
{
    float speed = 4.0f;
    void Start () { }
    void Update ()
	{
        Vector3 moveVector = new Vector3(-speed, 0.0f, 0.0f);
        transform.position += moveVector * Time.deltaTime;
    }
}

Lo script contiene una variabile speed che sarà utilizzata per controllare la velocità dei nostri nemici, la utilizziamo per farceli arrivare incontro (con segno negativo sull'asse X).

Aggiungere le collisioni

Non ci resta che rendere il nostro ragno sensibile alle collisioni con altri oggetti. Per farlo dobbiamo aggiungere i componenti Rigidbody e Box Collider all'oggetto Enemy.

Clicchiamo allora su Enemy e su Add Component nella finestra Inspector, poi cerchiamo rigidbody nella casella di ricerca. Una volta aggiunto il componente, per impedire movimenti indesiderati clicchiamo su Constraints e spuntiamo freeze rotation su tutti gli assi e freeze position sull'asse Z, poi togliamo il segno di spunta da Use Gravity.

Aggiungiamo allo stesso modo un Box Collider e assicuriamoci, il rettangolo di collisione dovrebbe comprendere automaticamente lo sprite e non dovremmo effettuare particolari impostazioni.

L'ultima cosa da fare è quella di aggiungere un tag ai nemici per riconoscerli facilmente dopo la collisione. Per farlo creiamo un nuovo tag per i nemici cliccando sulla proprietà Tag nella finestra Inspector e poi su Add Tag.... Chiamiamo il nuovo "tag Enemy":

Andiamo sullo script del nemico: per ora quel che ci interessa è togliere il nemico dalla scena. Questo se il nemico ha superato il giocatore, quindi non serve più visualizzarlo, oppure se ha coplito il nostro robottino:

using UnityEngine;
using System.Collections;
public class EnemyHandler : MonoBehaviour
{
    float speed = 4.0f;
    GameObject player;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.name == "Player")
            {
                Destroy(this.gameObject);
            }
        }
    }
    void Start()
    {
        GameObject _p = GameObject.Find("Player");
        if (_p != null)
        {
            player = _p;
        }
    }
    void Update()
    {
        Vector3 moveVector = Vector3.left;
        transform.position += moveVector * speed * Time.deltaTime;
        if (player != null)
        {
            if (this.transform.position.x <= player.transform.position.x - 10.0f)
            {
                Destroy(this.gameObject);
            }
        }
    }
}

Abbiamo implementato la funzione di callback per le collisioni: se il nemico urta l'oggetto "Player" rimuove se stesso dal gioco. Inoltre rimuoviamo il nemico se ha oltrepassato il giocatore già da un po'.

Se non lo abbiamo già fatto finora dobbiamo rendere lo sfondo non più sensibile alle collisioni. Per questo clicchiamo sul prefab Background nella cartella Prefabs e rimuoviamo il mesh collider:

In questo modo i nostri oggetti non collideranno con lo sfondo.

Rendere possibili le collisioni

Per rendere possibili le collisioni dobbiamo ripetere sul nostro personaggio le operazioni appena effettuate sul nemico. Clicchiamo quindi su Player, aggiungiamo un rigidbody, impostiamo i constraints (niente rotazioni e niente movimenti sull'asse Z), togliamo la spunta da Use Gravity e aggiungiamo il Box Collider.

Per testare il funzionamento sposiamo il nemico da qualche parte davanti al giocatore e premiamo play. Quando i due oggetti si incontrano il nemico scompare. Per vedere se il nemico viene cancellato anche quando esce di scena lasciamo andare l'azione e guardiamolo sparire dalla finestra Hierarchy.

Generare i nemici

Ora dobbiamo fare in modo che i nemici siano generati automaticamente nel tempo. Creiamo un nuovo script nella relativa cartella e lo chiamiamo GameHandler. Poi lo colleghiamo all'oggetto Main Camera, trascinandocelo sopra nella finestra Hierarchy.

Ora creiamo un prefab Enemy che utilizzeremo per creare tutti i nemici che ci servono direttamente dallo script. Quindi trasciniamo l'oggetto Enemy dalla finestra Hierarchy alla cartella Prefabs.

Fatto questo non ci servirà più sulla scena e quindi possiamo rimuoverlo dalla finestra Hierarchy (click destro du Enemy e poi Delete).

Ora possiamo modificare lo script GameHandler e implementare la logica per generare i nostri nemici:

using UnityEngine;
using System.Collections;
public class GameHandler : MonoBehaviour
{
    public int level;
    public GameObject enemy;
    public GameObject player;
	float spawnNewEnemyTimer = 10;
    void Start() { }
    void Update() {
        spawnNewEnemyTimer -= Time.deltaTime;
        if (spawnNewEnemyTimer <= 0)
        {
            spawnNewEnemyTimer = 5 - (level * 0.25f);
            Instantiate(enemy, new Vector3(player.transform.position.x + 50.0f,
                    player.transform.position.y, 0.0f), Quaternion.identity);
        }
    }
}

Anzitutto creiamo una variabile public chiamata level, che utilizzeremo per indicare quanto siamo avanti nel gioco. Aggiungiamo una seconda variabile (spawnNewEnemyTimer) che servirà a generare nemici ad un ritmo che aumenta in base al livello in cui siamo.

Iniziamo creando un nemico ogni 10 secondi (per dare al giocatore un po' più di tempo all'inizo). Man mano che il livello aumenta, si riduce il tempo che passa tra la creazione di un nemico e la successiva.

Quindi aggiungiamo due variabili public:

  • enemy, per ottenere un riferimento al prefab dei nemici, che vorremo istaziare;
  • player, che utilizziamo per referenziare il giocatore e conoscerne la posizione.

Ora torniamo all'editor di Unity e clicchiamo su Main Camera, poi trasciniamo dalla cartella Prefabs il prefab Enemy sulla variabile enemy dello script e facciamo lo stesso con l'oggetto Player dalla finestra Hierarchy.

Premiamo play e dopo i primi 10 secondi, vedremo apparire un nemico ogni 5 secondi. Riprenderemo la logica di gioco e dei livelli più avanti. Prima facciamo in modo che il robottino spari.

Creare il prefab per il laser

Il laser sarà un Quad che si sposterà ad una certa velocità da destra a sinistra finché non colpirà qualcosa o sparirà dallo schermo.

Lo creiamo al solito utilizzando un nuovo GameObject vuoto (GameObject > Create Empty), che chiamiamo Laser, al quale aggiungiamo un Quad (GameObject > Create Other > Quad), che chiamiamo Texture. Diamo al laser la classica forma modificando il fattore di scala in (0.5, 0.05, 1).

Ora creaimo un nuovo materiale nella cartella Materials e lo chiamiamo LaserMateriale gli assegnamo il rosso come Main color.

Impostiamo lo shader a Mobile/Particles/VertexLit Blend e assegamo di nuovo il colore rosso a Emissive Color. Fatto questo assegnamo il materiale all'oggetto Texture.

Ora aggiungiamo RigidBody all'oggetto Laser, con le solite impostazioni per i Constraints e togliendo la spunta da Use Gravity, poi un Box Collider. Ora siamo pronti a creare lo script per i laser.

Creiamo un nuovo script LaserHandler nella cartella Scripts e lo assegnamo all'oggetto Laser. Prima di scrivere il codice trasformiamo il laser in un prefab trascinandolo al solito dalla finestra Hierarchy alla cartella Prefabs, poi cancelliamo dalla scena il Laser e clicchiamo sullo script per modificarlo.

using UnityEngine;
using System.Collections;
public class LaserHandler : MonoBehaviour
{
    float speed = 16.0f;
    float aliveTimer = 2.0f;
    void Start () { }
    void Update () {
        aliveTimer -= Time.deltaTime;
        if (aliveTimer > 0.0f)
        {
            transform.position += Vector3.right * speed * Time.deltaTime;
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
}

Il codice fa spostare il laser e lo distrugge dopo due secondi se non ha colpito nulla.

Ora che il nostro Laser è pronto per essere creato a comando, dobbiamo modificare il nostro script del Player (PlayerHandler) per abilitarlo allo sparo:

using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour {
    float speed = 4.0f;
    public GameObject laserPrefab;
    float shootTimer = 0.0f;
    float setShootTimerTo = 0.5f;
    void Start () { }
    void Update () {
        Vector3 movePlayerVector = Vector3.right;
        shootTimer -= Time.deltaTime;
        if (Input.GetMouseButton(0))
        {
            Vector3 touchWorldPoint = Camera.main.ScreenToWorldPoint(
                new Vector3(Input.mousePosition.x,
                            Input.mousePosition.y,
                            10.0f));
            if (touchWorldPoint.x < this.transform.position.x + 5.0f)
            {
                if (touchWorldPoint.y > this.transform.position.y)
                {
                    movePlayerVector.y = 1.0f;
                }
                else movePlayerVector.y = -1.0f;
            }
            else
            {
                if (shootTimer <= 0)
                {
                    Vector3 shootPos = this.transform.position;
                    shootPos.x += 2;
                    Instantiate(laserPrefab, shootPos, Quaternion.identity);
                    shootTimer = setShootTimerTo;
                }
            }
        }
        this.transform.position += movePlayerVector * Time.deltaTime * speed;
        if (transform.position.y > -2.0)
        {
            transform.position = new Vector3(transform.position.x,
                                            -2.0f,
                                            transform.position.z);
        }
        if (transform.position.y < -5.5)
        {
            transform.position = new Vector3(transform.position.x,
                                            -5.5f,
                                            transform.position.z);
        }
    }
}

Abbiamo aggiunto una la variabile laserPrefab per referenziare il prefab del laser (ricordiamoci di collegare il prefab allo script) e un timer che controlla la frequenza di sparo.

Abbiamo aggiunto poi qualcosa al funzionamento dell'input. Se ora tocchiamo la parte sinistra dello schermo muoveremo il personaggio, se tocchiamo la parte destra lo facciamo sparare.

Se ora lanciamo il gioco il nostro personaggio potrà sparare, ma quando colpiremo il nemico non succederà nulla: dobbiamo modificare anche lo script del nemico (EnemyHandler) perché una volta colpito sparisca e con esso anche il laser:

using UnityEngine;
using System.Collections;
public class EnemyHandler : MonoBehaviour
{
    float speed = 4.0f;
    GameObject player;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.name == "Player")
            {
                Destroy(this.gameObject);
            }
            if (collision.rigidbody.CompareTag("Laser"))
            {
                Destroy(this.gameObject);
                Destroy(collision.gameObject);
            }
        }
    }
    void Start()
    {
        GameObject _p = GameObject.Find("Player");
        if (_p != null)
        {
            player = _p;
        }
    }
    void Update()
    {
        Vector3 moveVector = Vector3.left;
        transform.position += moveVector * speed * Time.deltaTime;
        if (player != null)
        {
            if (this.transform.position.x <= player.transform.position.x - 10.0f)
            {
                Destroy(this.gameObject);
            }
        }
    }
}

Ora ciò che facciamo è controllare che i laser siano etichettati con il tag Laser, quindi dobbiamo aggiungere ai tag un nuovo elemento "Laser" e assegnare al prefab Laser il tag "Laser", come abbiamo fatto prima per i nemici.

L'eccezione "Intertia Tensor"

Avrete certamente notato che la console segnala spesso una eccezione in questo modo:

"Actor::updateMassFromShapes: Compute mesh inertia tensor failed for one of the actor's mesh shapes! Please change mesh geometry or supply a tensor manually!"

Questo accade perché ci sono dei componenti Mesh Colliders sui nostri Quad. Sarà sufficiente rimuoverli dappertutto (nell'oggetto Texture del prefab Laser e nel background).

Creare le esplosioni

Quando un personaggio viene colpito vogliamo che "muoia" e vogliamo farlo esplodere! Prima di tutto fermeremo l'animazione della camminata e attiveremo quella della morte, solo dopo un attimo faremo in modo che esploda.

Per ottenere tutto questo modificheremo lo script EnemyHandler. Aggiungeremo due prefab che rappresenteranno l'esplosione e il fumo, quindi aggiungeremo una variabile booleana che indichi se il nemico è morto o meno e imposteremo un timer che ci aiuti a tenere traccia del tempo passato dalla morte e a lanciare l'esplosione dopo mezzo secondo (0.5s).

Per modificare l'animazione dei personaggi (giocatore e nemici) dobbiamo far riferimento alla funzione ChangeAnimationState del componente AnimationHandler.

Non è poi così complicato grazie alla funzione GetComponent che ci permette di accedere ai componenti di un certo GameObject. Facciamo un esempio supponendo di avere un oggetto player di cui modificare l'animazione:

((AnimationHandler) player.GetComponent()).ChangeAnimationState(1);

Quindi, quando il nemico viene colpito, impostiamo l'animazione a "morto" e assegnamo alla variabile booleana isDead il valore true.

Quando questa variabile è true iniziamo a generare lo smokePrefab e diamo il via al timer. Dopo 0.5 secondi il tempo scade, il nemico muore e viene generata un'esplosione.

Creiamo il prefab del fumo, trascinando prima l'immagine smoke dalla cartella Textures alla scena, poi trascinando il GameObject smoke dalla finestra Hierarchy alla cartella Prefab e infine cancellando l'oggetto smoke dalla scena. Il prefab dell'esplosione invece lo troviamo nella cartella Standard Assets/Particles/Legacy Particles. Dobbiamo ricordarci di collegare questi due prefab al prefab del nemico.

Ecco dunque il codice per EnemyHandler, che risulterà di semplice comprensione perché contiene tecniche che abbiamo già incontrare nel corso della guida:

using UnityEngine;
using System.Collections;
public class EnemyHandler : MonoBehaviour
{
    float speed = 4.0f;
    GameObject player;
    public GameObject explodePrefab;
    public GameObject smokePrefab;
    bool isDead = false;
    float isDeadTimer = 0.5f;
    AnimationHandler animationHandler;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.name == "Player")
            {
                Instantiate(explodePrefab, this.transform.position, Quaternion.identity);
                Instantiate(smokePrefab, this.transform.position, Quaternion.identity);
                Destroy(this.gameObject);
            }
            if (collision.rigidbody.CompareTag("Laser"))
            {
                isDead = true;
                Instantiate(smokePrefab, this.transform.position, Quaternion.identity);
                Destroy(collision.gameObject);
                if (animationHandler != null)
                {
                    animationHandler.ChangeAnimationState(2);
                }
            }
        }
    }
    void Start()
    {
        GameObject _p = GameObject.Find("Player");
        if (_p != null)
        {
            player = _p;
        }
        animationHandler = this.GetComponent<AnimationHandler>();
    }
    void Update()
    {
        if (isDead)
        {
            isDeadTimer -= Time.deltaTime;
        }
        else {
            Vector3 moveVector = Vector3.left;
            transform.position += moveVector * speed * Time.deltaTime;
        }
        if (player != null)
        {
            if (this.transform.position.x <= player.transform.position.x - 10.0f)
            {
                Destroy(this.gameObject);
            }
        }
        if (isDeadTimer <= 0.0f)
        {
            Instantiate(explodePrefab, this.transform.position, Quaternion.identity);
            Destroy(this.gameObject);
        }
    }
}

Aggiungere i punti vita al giocatore

Quando un ragno colpisce il robot ora appare un'esplosione, ma noi vogliamo che al giocatore succeda qualcosa, che "peggiori la sua salute". In altre parole, che i suoi punti-vita siano ridotti.

Modifichiamo lo script PlayerHandler, aggiungendo un counter per i punti vita (health point) e il gestore per le collistioni. In questo modo:

upublic class PlayerHandler : MonoBehaviour
{
    float speed = 4.0f;
    public GameObject laserPrefab;
    float shootTimer = 0.0f;
    float setShootTimerTo = 0.5f;
    public int HP;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.CompareTag("Enemy"))
                HP -= 1;
            }
        }
    }
// ...

Ora clicchiamo sul GameObject Player e impostiamo la proprietà HP a 10, poi lanciamo il gioco e controlliamo che HP cali ad ogni scontro con i nemici.

Per rendere un po' più visibile l'impatto che l'urto ha sul personaggio, facciamo in modo che il robot diventi rosso per un attimo dopo essere stato colpito e che torni pian piano al suo colore originale.

Modifichiamo ancora lo script PlayerHandler:

using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour
{
    float speed = 4.0f;
    public GameObject laserPrefab;
    float shootTimer = 0.0f;
    float setShootTimerTo = 0.5f;
    public int HP;
    float colorModifier = 1.0f;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.CompareTag("Enemy"))
            {
                HP -= 1;
                colorModifier = 0.0f;
            }
        }
    }
    void Start() { }
    void Update()
    {
        Vector3 movePlayerVector = Vector3.right;
        shootTimer -= Time.deltaTime;
        ((SpriteRenderer) this.GetComponentInChildren<SpriteRenderer>()).color =
            new Color(1.0f, colorModifier, colorModifier);
        if(colorModifier < 1.0f)
            colorModifier += Time.deltaTime;
// ...

Come si vede abbiamo utilizzato ancora un costrutto per ottenere i componenti degli oggetti, ma stavolta nella versione per accedere a quelli degli oggetti nidificati: GetComponentInChildren.

Il codice poi funziona in questo modo: all'inizio colorModifier è uguale a 0.0f (il ché modifica il colore in rosso e il robot cambia colore) e finché non diventa 1.0f lo incrementiamo 1.0f ( il ché modifica il colore in bianco, che consente la visualizzazione normale dello sprite). Ogni volta che il robot viene colpito riportiamo la variabile a 0 e la breve animazione ricomincia.

Aggiungere punti esperienza al giocatore (XP)

In questa fase vogliamo riconoscere al giocatore l'acquisizione di esperienza ogni volta che uccide un nemico. Lo facciamo con i punti esperienza (eXperience Points), che saranno utilizzati per aumentare il livello del gioco e la difficoltà.

Sempre nello script PlayerHandler, creiamo un nuovo intero che tenga conto dei punti esperienza e un altro in cui memorizziamo il livello del giocatore (l'altra variabile level che è nel GameHandler indica invece l'attuale livello che stiamo giocando e serve a regolare la frequenza di produzione dei nemici.

public class PlayerHandler : MonoBehaviour
{
    float speed = 4.0f;
    public GameObject laserPrefab;
    float shootTimer = 0.0f;
    float setShootTimerTo = 0.5f;
    public int Xp = 0;     // punti esperienza
    public int Level = 0;  // livello giocatore
    public int HP;
    float colorModifier = 1.0f;
// ...

Poi nello script dei nemici, quando ne uccidiamo uno, aggiungiamo esperienza al giocatore in base alla difficoltà del nemico. Modifichiamo lo script EnemyHandler:

using UnityEngine;
using System.Collections;
public class EnemyHandler : MonoBehaviour
{
    float speed = 4.0f;
    GameObject player;
    public GameObject explodePrefab;
    public GameObject smokePrefab;
    bool isDead = false;
    float isDeadTimer = 0.5f;
    public int enemyDifficulty;
    AnimationHandler animationHandler;
    PlayerHandler playerHandler;
    void OnCollisionEnter(Collision collision)
    {
        if (collision.rigidbody != null)
        {
            if (collision.rigidbody.name == "Player")
            {
                Instantiate(explodePrefab, this.transform.position, Quaternion.identity);
                Instantiate(smokePrefab, this.transform.position, Quaternion.identity);
                Destroy(this.gameObject);
            }
            if (collision.rigidbody.CompareTag("Laser"))
            {
                isDead = true;
                Instantiate(smokePrefab, this.transform.position, Quaternion.identity);
                Destroy(collision.gameObject);
                if (animationHandler != null)
                {
                    animationHandler.ChangeAnimationState(2);
                }
            }
        }
    }
    void Start()
    {
        GameObject _p = GameObject.Find("Player");
        if (_p != null)
        {
            player = _p;
            playerHandler = player.GetComponent<PlayerHandler>();
        }
        animationHandler = this.GetComponent<AnimationHandler>();
    }
    void Update()
    {
        if (isDead)
        {
            isDeadTimer -= Time.deltaTime;
        }
        else {
            Vector3 moveVector = Vector3.left;
            transform.position += moveVector * speed * Time.deltaTime;
        }
        if (player != null)
        {
            if (this.transform.position.x <= player.transform.position.x - 10.0f)
            {
                Destroy(this.gameObject);
            }
        }
        if (isDeadTimer <= 0.0f)
        {
            Instantiate(explodePrefab, this.transform.position, Quaternion.identity);
            Destroy(this.gameObject);
            playerHandler.Xp += enemyDifficulty * 10;
        }
    }
}

Abbiamo creato una nuova variabile public per il nemico per introdurre la difficoltà nel livello. Nella funzione Start prendiamo il riferimento allo script del giocatore e lo utilizziamo per modificarne i punti esperienza (10 x livello di difficoltà) quando il nemico muore.

Impostiamo quindi il livello di difficoltà a 1 nel prefab dei nemici.

Aumentare il livello del giocatore

Ora possiamo aumentare il livello del giocatore in base ai suoi punti esperienza. Lo facciamo nello script PlayerHandler: creiamo una tabellina che associ le soglie di punti esperienza necessari a raggiungere i relativi livelli.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PlayerHandler : MonoBehaviour
{
    float speed = 4.0f;
    public GameObject laserPrefab;
    float shootTimer = 0.0f;
    float setShootTimerTo = 0.5f;
    public int Xp = 0;
    public int Level = 0;
    List<int> levelList = new List<int>();
	// ...
    void OnCollisionEnter(Collision collision)
    {
        // ...
    }
    void Start() {
		// Popoliamo la lista delle soglie
        for (int i = 0; i < 20; i++)
        {
            levelList.Add((int)(50 + (i * 50) + (i * 50 * 0.25)));
        }
    }
    void Update()
    {
        Vector3 movePlayerVector = Vector3.right;
        shootTimer -= Time.deltaTime;
        ((SpriteRenderer) this.GetComponentInChildren()).color =
            new Color(1.0f, colorModifier, colorModifier);
        if(colorModifier < 1.0f)
            colorModifier += Time.deltaTime;
		// Aumentiamo il livello al raggiungimento del punteggio necessario
        if (Xp >= levelList[Level])
        {
            Level++;
        }
		// ...
    }
}

Nello script GameHandler dovremmo fare in modo che il gioco diventi sempre più difficile man mano che si gioca. Ci sono diverse scelte di design possibili per ottenere questo effetto: potremmo collegare il livello del gioco al livello del giocatore oppure decidere che il gioco diventi difficile col passare del tempo. Scegliamo la prima ipotesi.

In GameHandler, creiamo un riferimento a PlayerHandler, quindi impostiamo l'intero level del gioco uguale al level del giocatore:

public class GameHandler : MonoBehaviour
{
    public int level;
    public GameObject enemy;
    public GameObject player;
	// riferimento al PlayerHandler
    public PlayerHandler playerHandler;  
    float spawnNewEnemyTimer = 3;
    void Start() {
		// prendiamo il component dal player
        playerHandler = player.GetComponent<PlayerHandler>();
    }
    void Update()
    {
		// adeguiamo il livello del gioco a quello del giocatore
        if (playerHandler != null)
        {
            level = playerHandler.Level;
        }
		// ...
	}
	// ...
}

Ora facciamo il gioco ancora un po' più complicato: dal livello 2 in su genereremo 2 nemici alla volta invece che uno solo. Modifichiamo ancora il GameHandler:

using UnityEngine;
using System.Collections;
public class GameHandler : MonoBehaviour
{
    public int level;
    public GameObject enemy;
    public GameObject player;
    public PlayerHandler playerHandler;
    float spawnNewEnemyTimer = 10;
    // Use this for initialization
    void Start()
    {
        playerHandler = player.GetComponent<PlayerHandler>();
    }
    // Update is called once per frame
    void Update()
    {
        spawnNewEnemyTimer -= Time.deltaTime;
        if (spawnNewEnemyTimer <= 0)
        {
            spawnNewEnemyTimer = 5 – (level * 0.25f);
            if (spawnNewEnemyTimer < 0.5f)
                spawnNewEnemyTimer = 0.5f;
            int spawnNumberOfEnemies = 1 + (level/3);
            for (int i = 0; i < spawnNumberOfEnemies; i++)
            {
                float modifier = Random.Range(0.0f, 1.0f);
                Instantiate(enemy, new Vector3(player.transform.position.x + 100.0f + i*10,
                       player.transform.position.y + modifier, 0.0f), Quaternion.identity);
            }
        }
        if (playerHandler != null)
        {
            level = playerHandler.Level;
        }
    }
}

La logica che abbiamo implementato farà in modo che il gioco produca un numero di nemici proporzionale al livello cui siamo. Se siamo a livello 1 o 2 avremo un nemico alla volta e ogni 3 livelli avremo un nemico in più alla volta.

Ti consigliamo anche