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!

Nessun commento:

Posta un commento