Nella scorsa lezione abbiamo visto alcuni degli elementi base per scrivere script per il nostro gioco in Unity.

In questa seconda parte amplieremo il discorso introducendo tanti nuovi elementi e scrivendo alcuni script che, a differenza dei precedenti, avranno un impatto tangibile sul nostro gioco!

Prima però mettiamo da parte Unity per un attimo e completiamo il discorso sulle basi della programmazione in C# che abbiamo lasciato in sospeso:

Le istruzioni condizionali if-else

Questo tipo di istruzioni permettono di gestire l’esecuzione di una porzione di codice. Il funzionamento di un’istruzione if-else si basa sulla verifica di una o più condizioni da noi imposte secondo la seguente sintassi:

if(condizione){

} else {

}

se la condizione che abbiamo imposto viene soddisfatta verrà eseguito il codice che abbiamo scritto fra le prime parentesi graffe, mentre se la condizione non viene soddisfatta verrà eseguito il codice nelle parentesi graffe dopo l’else.

Ad esempio:

if(tuoNome == "Mario"){
   Debug.Log ("Il tuo nome è Mario!");
} else {
   Debug.Log("Il tuo nome NON è Mario!);
}

come puoi vedere , nel caso in cui una variabile (che qui abbiamo chiamato tuoNome) sia uguale a “Mario” verrà eseguita una parte di codice, mentre in caso contrario ne verrà eseguita un’altra.

Probabilmente ti starai chiedendo perchè nella condizione sia presente un doppio uguale.

Parleremo delle condizioni e della loro sintassi fra pochissimo,ma per il momento mettiamo la questione da parte!

L’istruzione if-else presenta molte sfumature diverse che possiamo utilizzare nei casi più disparati.

Possiamo ad esempio scrivere qualcosa di simile:

Debug.Log("Ciao!");

if (tuoNome == "Luca"){
    Debug.Log("Abbiamo lo stesso nome!");
}

Debug.Log("è stato un piacere conoscerti!");

In questo caso il nostro codice presenta solo un if ed ha perso l’else che abbiamo visto nel caso precedente.

Se la condizione è verificata (cioè se la variabile “tuoNome” è uguale a Luca) verrà eseguito il codice contenuto nel corpo dell’istruzione if (che da questo momento chiameremo if statement, giusto per sembrare più professionali).

Mentre, la parte seguente l’if (cioè il Debug.Log (“è stato un piacere conoscerti!”); ) verrà eseguita in ogni caso.

Altra variante interessante è quella contenente degli else if:

if (tuoNome == "Luca") {
   Debug.Log("Abbiamo lo stesso nome!");
}
else if (tuoNome == "Mario") {
   Debug.Log("Come Super Mario!");
}
else if (tuoNome == "Luigi") {
   Debug.Log("Come il fratello di Super Mario!");
}
else {
   Debug.Log("Che bel nome!");
}

In questo caso, a valori diversi della variabile “tuoNome” corrispondono diverse istruzioni.

Se la variabile sarà uguale a “Luca” verrà eseguito il codice del primo statement ed i successivi verranno scartati. Mentre, se la variabile è uguale a “Mario“, verrà eseguito il corpo dell’else-if corrispondente.

Se la variabile dovesse avere un valore che non sia Luca, Mario o Luigi, allora verrà eseguito il codice contenuto nell’else!

Chiaramente possono essere inseriti else if a piacere, in base a quante diverse opzioni si vogliono avere.

Le condizioni

Una parte fondamentale di questo tipo di istruzioni sono le condizioni.

Queste confrontano fra loro due valori tramite alcuni operatori condizioniali e assumono valore vero se la condizione imposta viene verificata, o diversamente, assumono valore falso se la condizione non viene verificata.

Abbiamo già visto l’operatore di uguaglianza (scritto come “==“), che fa sì che la condizione sia vera se i due elementi sono uguali fra loro.

Opposto all’operatore di uguaglianza abbiamo quello di disuguaglianza, che si esprime tramite il simbolo “!=” e si attiva soltanto se i due valori sono diversi fra loro.

Inoltre esistono gli operatori di maggioranza (“>“) o di minoranza(“<“), che come suggerisce il nome si attivano quando il valore di una variabile numerica è (nemmeno a dirlo) maggiore (o minore) di un certo valore, sia esso un numero fisso o un’altra variabile.

Facciamo un esempio e supponiamo di avere anche una variabile di tipo int contenente la tua età:

if ( tuoNome != "Luca") {
    Debug.Log("I nostri nomi sono diversi!");
}
if ( tuaEtà > 25) {
    Debug.Log("Sei più grande di me!");
}
if ( tuaEtà < 25) {
    Debug.Log("Sei più piccolo di me!");
}
if ( tuaEtà == 25) {
    Debug.Log("Siamo coetanei!");
}

Gli operatori booleani

In moltissimi casi avremo bisogno di imporre più di una condizione per regolare l’accesso alle nostre istruzioni. Possiamo farlo facilmente tramite gli operatori booleani.

Qui di seguito vedremo velocemente i due operatori booleani più importanti: l’AND e l’OR!

L’AND (che utlizza il simbolo “&&“) sarà vero solo se saranno verificate entrambe le condizioni fra cui è inserito, mentre l’OR (che invece utilizza il simbolo “||“) sarà vero se è verificata almeno una delle due condizioni fra cui è inserito. Vediamo un esempio:

if (tuoNome == "Luca" && tuaEtà == 22) {
   Debug.Log("Abbiamo lo stesso nome e la stessa età!");
}
if (tuaEtà < 22 || tuaEtà > 22) {
   Debug.Log("Non abbiamo la stessa età!");
}

A questo punto abbiamo tutti gli strumenti fondamentali per poter scrivere alcuni semplici script per il nostro gioco.

Riapriamo quindi Unity e vediamo come manipolare i nostri Game Objects!

Accendere e spegnere una luce

Il primo script che andremo a scrivere sarà piuttosto semplice: faremo in modo di poter accendere e spegnre una luce nella nostra scena con la pressione di un tasto.

Impostiamo una semplice scena con qualche oggetto ed una spotlight ben visibile (qualcosa di simile alla foto qui sotto andrà benissimo)

1001

Selezioniamo quindi la nostra Spotlight e tramite il classico “Add Component” aggiungiamole uno script che chiameremo “LightScript“.

Apriamolo in Visual Studio e iniziamo a ragionare su come scrivere il nostro script!

La prima cosa da fare è inizializzare le variabili di cui avremo bisogno.

Qui la domanda che potresti porti è: “Come faccio ad accedere alle proprietà della spotlight?”

Ebbene, devi sapere che in Unity qualsiasi componente di un gameobject può essere utilizzato come un tipo di dato!

All’inizio del nostro script quindi, prima del metodo Start():

  1. Inizializziamo un oggetto di tipo light per controllare i vari parametri del componente light
  2. e un booleano che contenga lo stato attuale della lampadina (e cioè che sia vero se la luce è accesa e falso se la luce è spenta.

Li chiameremo rispettivamente “spotlight” e “isTurnedOn“. Dato che al momento la luce è accesa, dobbiamo inizializzare il valore della variabile “isTurnedOn” come vero.

Per il momento inizializzeremo le variabili come segue:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LightScript : MonoBehaviour {
   public Light spotlight;
   public bool isTurnedOn = true;
 
   // Use this for initialization
   void Start () {
 
   }
 
   // Update is called once per frame
   void Update () {
   }

}

per verificare la pressione di un tasto utilizzeremo il metodo “Input.GetKeyDown, che come possiamo leggere dalla sua descrizione, verrà attivato alla pressione di un determinato tasto.

In questo caso utilizzeremo il tasto A della nostra tastiera (che assegneremo allo script tramite la dicitura “KeyCode.A“).

Cosa dovrà fare il nostro script alla pressione del tasto A?

Dovrà semplicemente controllare se la luce è attualmente spenta o accesa, e lo farà leggendo il valore della nostra variabile booleana “isTurnedOn“.

Nel caso la variabile sia vera (e quindi la luce accesa) il codice dovrà provvedere a spegnere la luce e a cambiare il valore della variabile booleana in “false” (per indicare quindi che da questo momento la luce sarà spenta).

Al contrario, se la luce è già spenta, dovrà provvedere ad accenderla e ad impostare il valore della variabile booleana in “true“.

Per modificare il valore della spotlight da acceso a spento (o viceversa) bisogna accedere ad uno dei valori del nostro componente light e modificarlo.

Abbiamo già inizializzato un componente di tipo light all’interno di questo script, e richiamandolo all’interno dello script seguito da un punto (esattamente come abbiamo visto nella scorsa lezione col metodo “Debug.Log“) vedremo tutte le funzioni ed i parametri propri di un oggetto di tipo “light“.

Potremo modificare colore, luminosità, ampiezza e tutti i valori propri di una luce!

In questo caso vorremo accedere al parametro “enabled“, che come possiamo leggere dalla sua descrizione, digitando “spotlight.enabled“, è il parametro che ci dice se la componente light è attiva o meno.

Ecco quindi il nostro script in tutta la sua bellezza:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LightScript : MonoBehaviour {
   public Light spotlight;
   public bool isTurnedOn = true;

   // Use this for initialization
   void Start () {
   }
 
   // Update is called once per frame
   
   void Update () {
      if(Input.GetKeyDown(KeyCode.A) && isTurnedOn == true){
          spotlight.enabled = false;
          isTurnedOn = false;
          Debug.Log("La luce è spenta!");
      }
      else if(Input.GetKeyDown(KeyCode.A) && isTurnedOn == false){
         spotlight.enabled = true;
         isTurnedOn = true;
         Debug.Log("La luce è accesa!");
      }
   }

}

Affinchè lo script funzioni correttamente dobbiamo salvarlo (come al solito) e successivamente assegnare la luce da manipolare allo script, come mostrato nella seguente animazione:

anim1001

A questo punto il nostro script funziona, ma non è ancora perfetto!

Sarebbe meglio infatti nascondere dall’inspector panel sia la variabile booleana “Is Turned On” che la spotlight stessa.

Come puoi notare infatti cliccando sulla casella della variabile “Is Turned On” puoi compromettere il funzionamento stesso dello script.

Se vogliamo evitare disastri accidentali la regola da seguire è nascondere tutti i dati che non devono essere manipolati direttamente!

Come fare, quindi?

Se per quanto riguarda la variabile booleana basta dichiararla come private. Per l’oggetto light la questione è appena più complessa. Perchè come abbiamo visto è necessario assegnargli il componente light dell’oggetto affinché funzioni.

Per farlo in maniera automatica esiste una funzione specifica, la GetComponent, che non fa altro che collegare ad un elemento del nostro script l’elemento dello stesso tipo presente nello stesso oggetto.

In questo caso provvederà quindi ad assegnare la componente light dell’oggetto Spotlight alla variabile spotlight interna al nostro script! In parole povere, automatizza quell’assegnazione che nell’animazione abbiamo eseguito a mano.

Il nostro script adesso apparirà così:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LightScript : MonoBehaviour {
   private Light spotlight;
   private bool isTurnedOn = true;
    
   // Use this for initialization
   void Start () {
      spotlight = GetComponent<Light>();
   }
 
   // Update is called once per frame
   void Update () {
      if(Input.GetKeyDown(KeyCode.A) && isTurnedOn == true){
         spotlight.enabled = false;
         isTurnedOn = false;
         Debug.Log("La luce è spenta!");
      }
      else if(Input.GetKeyDown(KeyCode.A) && isTurnedOn == false){
         spotlight.enabled = true;
         isTurnedOn = true;
         Debug.Log("La luce è accesa!");
      }
   }
}

Facciamo saltare un cubo!

Il prossimo script che andremo a scrivere sarà simile al precedente per moltissimi aspetti.

Questa volta faremo saltellare un cubo.

Inseriamo un cubo nella nostra scena (se l’hai già fatto in precedenza puoi usare quello!) ed assegniamogli un componente RigidBody: ci servirà per aggiungere una forza al cubo (e di conseguenza farlo saltare).

Inseriamo quindi un nuovo script di nome CubeJump. Il codice che utilizzeremo sarà il seguente:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeJump : MonoBehaviour {
   private Rigidbody rb;
   public int altezzaSalto = 200;
 
   // Use this for initialization
   void Start () {
      rb = GetComponent<Rigidbody>();
   }
 
   // Update is called once per frame
   void Update () {
      if(Input.GetKeyDown(KeyCode.Space)){
         rb.AddForce(Vector3.up * altezzaSalto);
      }
   }
}

Come puoi vedere la logica è molto simile a quella dello script precedente, ma in questo caso abbiamo assegnato il salto del cubo alla barra spaziatrice della nostra tastiera (come in qualsiasi gioco che si rispetti!).

Poi abbiamo fatto uso del metodo AddForce per aggiungervi una forza.

Il metodo Addforce accetta solo dati di tipo Vector3, cioè un tipo di dati che contiene delle coordinate di tipo x,y,z, cioè un vettore nello spazio!

Abbiamo già accennato al significato di vettore, che detta banalmente altro non è che una freccia con una data direzione ed una sua specifica lunghezza.

Normalmente bisognerebbe descrivere questi vettori per intero specificandone la lunghezza lungo ogni coordinata, ma in questo caso possiamo utilizzare il metodo Vector3.up , che equivale ad un vettore (x,y,z) con y = 1 e x,z=0 (in pratica, una freccia che va verso l’alto!).

Applicando all’oggetto una forza del genere gli daremmo una spinta verso l’alto, ma poichè il valore è di default troppo basso occorre moltiplicarlo per un variabile pubblica da noi definita, in modo da poter apprezzare un salto di un’altezza decente e manipolare quest’ultima anche dall’esterno dello script!

anim1002

I commenti del codice

Prima di chiudere questa lezione, voglio darti alcuni consigli sulla scrittura di codice in Unity:

Per prima cosa: utilizza i commenti!

Essi sono delle righe di codice che vengono escluse dalla compilazione, e vengono usati per descrivere brevemente una parte del codice.

Fidati, è importante commentare il codice sia per renderlo comprensibile ad altri.

Ipotizza ad esempio di lavorare in un team, o comunque con altre persone: dovrebbero rileggere tutto il codice ed entrare nella tua testa per capire il ragionamento che hai fatto per arrivare a scrivere quelle righe di codice.

Ma, usali sopratutto, per rendere il codice comprensibile a te stesso in futuro.

Non è difficile dimenticare il funzionamento di uno script realizzato tempo prima, e creando un gioco potresti ritrovarti a modificare script scritti settimane, o mesi prima.

Commentare il codice ti renderà il lavoro molto più semplice!

Un commento può essere scritto in due modi:

  1. preceduto dal simbolo //
  2. o inserito fra i simboli “/*” e “*/”.

Nel primo caso il commento deve essere contenuto interamente in una riga (verranno escluse dalla compilazione solo quelle parti di codice che seguono il simbolo “//” e che appartengono a quella determinata riga), mentre nel secondo caso il commento può occupare più righe.

Esempio:

//io sono un commento!


/*io

sono

un

commento! */

Probabilmente li avrai già visti, perchè alla creazione degli script in Unity vengono già inseriti dei commenti per descrivere le funzioni Start() ed Update()!

L’altro consiglio che voglio darti è quello di consultare spesso e volentieri la documentazione ufficiale di Unity.

Qui troverai la descrizione e la sintassi di tutte le funzioni e tutti i metodi da utilizzare in Unity, completi di alcuni esempi!

Conclusione

Per questa lezione è tutto.

Nella prossima parleremo di interfaccia utente e vedremo come creare un menù principale per il nostro gioco, ma non solo.

Vedremo anche come far apparire punteggi, bottoni, menù di pausa e quant’altro!

Back to: Unity Bootstrap: Corso gratuito sviluppo giochi con Unity 3D. Le basi di Unity dalla A alla Z > Unity Bootstrap Lezioni