mercoledì 9 novembre 2016

InViaggio: Cascata di Colori

InViaggio: Esplosione di Colori

La serie InViaggio tratta di piccoli programmi fatti mentre sono in treno

Obbiettivo: creare un generatore di diverse forme di vario colore in (0,0,0)


Progetto
Vogliamo avere un vettore statico di oggetti primitivi a cui assegnare un materiale da colorare successivamente. Dunque:



Gli oggetti da spawnare sono selezionabili nell'inspector:

Vogliamo ciclare tra tutti gli elementi del vettore alla pressione di qualsiasi tasto (sia della tastiera, che del mouse, o al tocco su iPhone/AndroidPhone). Dunque:
L'oggetto viene creato, ma in una posizione casuale! Centriamo l'oggetto appena creato in (0,0,0) e, allo scopo di farlo cadere nel vuoto, aggiungiamo un RigidBody alla quale applichiamo una forza in una direzione casuale:



Ora, vogliamo cambiare il colore all'oggetto appena creato. Ciò viene fatto aggiungendo un componente Renderer al tipo primitivo, assegnandogli un materiale e dandogli un colore casuale tramite l'apposita funzione contenuta in Random:
 (qui correggo una piccola distrazione: l'if che contiene l'indice và dentro la condizione di Input, non fuori!)



 L'unico problema è che gli oggetti così creati non vengono distrutti! Aggiungiamo un piccolo script che distrugge gli oggetti spawnati dopo pochi secondi:
ed aggiungiamo questa riga allo script precedente:
Risultato:
Voilà! Modificando leggermente lo script, è possibile far spawnare anche oggetti creati ad hoc.

Clicca qui per scaricare il materiale!



domenica 16 ottobre 2016

Frattale

Progetto Base: Frattale

Obiettivi

  • Instanziare oggetti da script
  • Ricorsione
  • Coroutine
 

Progetto

L'idea è di creare un frattale a partire da un oggetto di base, creado di iterazione in iterazione dei figli del tutto identici all'originale se non per dimensione. È un buon esercizio mentale, senza contare che si può lavorare su di un concetto fondamentale, l'iterazione.

Creiamo un oggetto vuoto nella scena, ed assegnamo la classe "Frattale"
Dunque, vogliamo che il frattale parta da una certa mesh che gli assegneremo in partenza e, da lì, che calcoli e instanzi i figli. La classe dovrà avere dunque 2 variabili pubbliche MeshRenderer e MeshFilter.


Assegnamo dall'Inspector un materiale creato ad hoc e scegliamo una mesh dalle primitive di Unity.






Aggiungiamo dunque dei figli al frattale. Il modo più semplice con cui aggiungere dei figli ad un oggetto tramite script è tramite la sintassi:



Con tale sintassi, però, vengono istanziati infiniti oggetti Frattale, con il risultato di far bloccare il PC. Introduciamo quindi una variabile che definisce il numero massimo di iterazioni ed il numero corrente di iterazioni:
 E le inizializziamo tramite il metodo di Unity Initialize():




Vengono dunque creati, così, 4 figli nella gerarchia. Tuttavia noi vogliamo che gli oggetti siano figli dell'oggetto frattale principale. Cioè:
E lo facciamo tramite il comando transform.setParent(Genitore.transform); :

Tuttavia anche così i figli istanziati rimangono nella stessa posizione del padre. Introduciamo una variabile per gestire la scala dei figli e li posizioniamo sopra l'oggetto di Origine:
Il risultato:
Un vero frattale, però, ha figli anche nelle altre direzioni. Ristrutturiamo dunque il metodo Initialize() per includere la direzione nella quale istanziare i figli:

Il risultato:
Ora, il problema è che, ipotizzando di istanziare figli su tutte le 6 facce del cubo, si otterrebbe che in pochi frame si istanziano 6^4 = 1296 oggetti, con conseguente rallentamento ed impossibilità di vedere il frattale effettivamente "crescere". Poniamo dunque un intervallo tra una istanziazione e l'altra attraverso la creazione di un metodo IEnumerator e l'utilizzo di StartCoroutine(). Dunque:




Bene, ma non benissimo. I figli vengono istanziati in piccole raffiche che causano ancora rallentamenti. Introduciamo dunque un ritardo randomico a WaitForSeconds in modo da distribuire la creazione dei figli in un certo intervallo di tempo:
C'è ancora un problema: i figli vengono instanziati all'interno del padre. Utilizzando la visuale Overdraw questo è piuttosto evidente:
Vogliamo dunque ruotare i figli nella direzione in cui si istanziano. Per fare questo rimuoviamo l'istanziazione a Vector3.down, e rimaniamo le altre, aggiungendo ad Initialize() un altro parametro per gestire la rotazione:

Il risultato:

Tuttavia questo fa rimanere una parte del frattale vuota. Dunque, ristrutturando brevemente e concisamente il codice possiamo fare in modo che l'istanziazione dei figli sia indicizzata:

tale risultato è raggiunto semplicemente aggiungendo dei vettori con la posizione e la rotazione dei figli come variabili private, ed aggiustando in modo consono Initialize(). Il risultato è identico a  prima, ma ora possiamo aggiungere semplicemente le direzioni in cui vogliamo i figli:

Ed il risultato:

abbiamo ottenuto il frattale completo! Possiamo apportare infinite modifiche, da questo punto in poi: possiamo dare un colore diverso ad ogni componente, farli lampeggiare, aggiungere rotazioni extra ai figli, farli istanziare in modo asimmetrico...le possibilità sono legate solo alla fantasia (e pazienza!).

Clicca qui per scaricare il materiale!

venerdì 14 ottobre 2016

Orologio

Progetto Base: Orologio

Obbiettivi

  • Creare una gerarchia di oggetti
  • Creare uno script
  • Usare i namespace
  • Usare la funzione Update()

Progetto

Iniziamo col creare un nuovo progetto. La scena di default inizia con due componenti, la Main Camera posizionata alle coordinate (0,1,-10) e la Directional Light alle coordinate (0,3,0).

 

Necessitiamo di una struttura per costruire l'orologio. Questo orologio sarà composto da semplici cubi, animati attraverso scripts.

Creiamo dunque nel pannello della gerarchia (eng. Hierarchy) un nuovo oggetto vuoto attraverso Create -> Create Empty. Con lo stesso procedimento, avendo selezionato il nuovo oggetto vuoto, creiamo tre cubi attraverso Create->3D Object->Cube, rendendoli dunque figli del nuovo oggetto. Rinominiamo il nuovo oggetto creato "Orologio", ed impostiamo le sue coordinate a (0,0,0).

   

Rinominiamo i cubi creati in "Ore", "Minuti", "Secondi" e cambiamo le scale in modo da avere come posizioni (0, 1, 0),(0, 1.5, 0),(0, 2, 0) e come scala (0.5, 2, 0.5),(0.25, 3, 0.25),(0.1, 4, 0.1), rispettivamente per le ore, i minuti ed i secondi.

Passiamo ora ad animare l'orologio.

Creiamo uno script nella vista del Progetto e chiamiamolo "Animatore_Orologio". Lo apriamo e cominciamo a scrivere le 3 variabili Transform delle Ore, Minuti e Secondi. Attacchiamo questo script all'oggetto creato (io ne ho creato un'altro chiamato "Detentore_Scripts". In genere è l'oggetto che detiene tutti gli script che si occupano di gestire script da non assegnare ad altri oggetti, dunque unici) e trasciniamo sopra le lancette ai relativi campi.


Notiamo che stiamo usando il namespace di UnityEngine, senza il quale non potremmo includere MonoBehaviour.

   

 Cominciamo ora a scrivere:

 

Come dovrebbe muoversi l'orologio? Consideriamo, per ora, un orologio digitale.
Consideriamo la lancetta delle ore. Per compiere un giro completo (360°) deve fare 12 passi; la lancetta dei minuti, invece, 60, come la lancetta dei secondi. Dunque si ha:
la variabile "in_Analogico" tornerà utile più tardi.

 Vogliamo conoscere il tempo ad ogni aggiornamento, dunque scriviamo:




Vogliamo dunque ruotare le lancette modificandone la rotazione:






Abbiamo ora un orologio digitale in tempo reale. E se ne volessimo uno analogico?

Per cambiare da analogico a digitale ci basta premere il segno di spunta.

Clicca qui per scaricare il materiale!

Premessa

Questo blog seguirà i miei sforzi di imparare meglio Unity.

Scelgo di scrivere queste "guide" sotto forma di testo e non di video perché il testo è più facile da seguire, interrompere, riadattare al proprio ritmo di pensiero.

Ogni post si prefiggerà come obbiettivo di completare un progetto (o parte di esso) più o meno semplice, spiegando al contempo il perché di di determinate scelte, corredando il tutto con codice, illustrazioni e, alla fine del post, con il materiale sviluppato scaricabile gratuitamente sotto forma di .unitypackage . Sentitevi liberi di farne ciò che volete.

Gli script saranno scritti in C#, questo per due motivi principali:
  • C# ha una sintassi più restrittiva di Javascript, imponendo un certo ordine di pensiero rispetto a linguaggi più libertari.
  • Javascript in Unity non è effettivamente Javascript, ma una versione modificata chiamata Unityscript, che sta venendo lentamente abbandonata. C#, invece, può fare uso anche di tutte le librerie proprie (es. System.IO)
Farò del mio meglio per nominare tutte le variabili in italiano comprensibile e  per spiegare tutte le funzioni di Unity. I link che posterò di riferimento saranno per forza di cosa in inglese, dal momento che sarebbe troppo costoso, in termini di tempo, tradurre interi libri di riferimento (sic!) di Unity.