1. INTRODUZIONE
2.1 UNREAL ENGINE
2.1.1 CENNI STORICI
La prima versione del motore fu sviluppata interamente da Tim
Sweeney, fondatore della Epic Games. Egli, ispirato dai pionieristici
capolavori di John Carmack, quali Doom e Quake, decise di realizzare il proprio sparatutto in prima persona (FPS), denominandolo Unreal.
Parallelamente con la creazione del gioco, iniziata nel 1995, anche la prima embrionale versione dell'engine prese forma, debuttando ufficialmente nel 1998.
Seppur ancora agli albori, il motore già era provvisto di meccanismi per l'hardware ed il software rendering, per la collision detection, per il
colored lighting e per il texture filtering. Era, inoltre, già presente un editor di livelli denominato UnrealEd, capace di supportare la constructive geometry.
Le piattaforme compatibili furono, fin da subito, Windows, Linux e
MacOS. Negli anni il target sarebbe stato poi esteso anche alle principali
console esistenti (PlayStation 2, PlayStation 3, PlayStation 4, Xbox,
Xbox360, XboxOne, GameCube, Wii, WiiU, Nintendo Switch), così come al mondo del mobile (Android, iOS).
La popolarità dell'engine crebbe rapidamente soprattutto grazie alla sua intrinseca modularità, nonché grazie all'introduzione di un comodo
come si dice in gergo, "moddare" il sistema. Scopo della modularità era quello di rendere il motore flessibile ed estensibile, capace di resistere, pertanto, ad innumerevoli generazioni di videogiochi. Citiamo, a tal proposito, le parole dello stesso Tim Sweeney:
"... the big goal with the Unreal technology all long was to build up a base of code that could be extended and improved through many generations of games. Meeting that goal required keeping the technology quite general purpose, writing clean code and designing the engine to be very extensible ..."
Unreal (EpicGames, 1998), Unreal Tournament (EpicGames, 1999), DeusEx (Eidos, 2000), sono tutti esempi di titoli famosissimi sviluppati con
Unreal Engine 1.
Figura 2.38: Immagini di gameplay di Unreal Tournament su Windows XP.
La seconda versione del motore fece la sua comparsa nel 2002, recando con sé un nuovo renderer, l'editor di cinematics Matineè ed un file exporter per 3D Studio Max e Maya, così come il motore fisico Karma. Apparve anche UnrealEd3, la nuova versione dell'editor di livelli.
Tra i videogiochi di maggior successo realizzati con UnrealEngine 2 ricordiamo: Tom Clancy's Splinter Cell (Ubisoft, 2002) e Bioshock (2K
Games, 2007).
Figura 2.39: Immagine di gameplay di Tom Clancy's Splinter Cell su PlayStation 2.
La terza versione dell'engine è sicuramente quella che finora ha riscosso il maggior successo in termini di popolarità ed utilizzo. Presentata nel 2004, la principale innovazione che introdusse fu la sostituzione della vecchia rendering pipeline fissa, con una nuova pipeline basata interamente sugli shader. Utilizzato per più di dieci anni è stato esteso e potenziato nel tempo con l'introduzione di numerosissime feature, tra le quali: ambienti distruttibili (destructible environments), dinamica dei corpi morbidi (soft body dynamics), simulazione di folle (large crowd simulation),
illuminazione globale in tempo reale (real time global illumination).
Mass Effect (Bioware, 2007) è stata programmato tramite Unreal Engine 3, così come Mirror's Edge (EA Digital Illusions CE, 2008), Batman Arkham City (Rocksteady Studios, 2011), DmC: Devil May Cry
(Ninja Theory, 2013) e numerosissimi altri giochi tripla A pubblicati nello scorso decennio.
Figura 2.40: Immagini di gameplay di DmC Davil May Cry su Xbox 360.
La versione dell'engine correntemente utilizzata è però la quarta (Unreal Engine 4), la quale è frutto di dieci anni di studio e si sviluppo ed è stata presentata ufficialmente nel 2014.
Tra le principali novità che ha portato con sé ricordiamo la hot compilation e l'innovativo modello dei blueprints. Di quest'ultimo
argomento discuteremo a breve.
Gears Of War 4 (The Coalition, 2016), Fortnite (Epic Games,
2017), Kingdom Hearts 3 (Square Enix, in uscita a Gennaio 2019) sono validissimi esempi di titoli creati sfruttando l'enorme potere dell'Unreal Engine 4.
Figura 2.41: Immagini di gameplay di Fortnite su Windows 10.
2.1.2 STRUTTURA E TERMINOLOGIA
L'Unreal Engine 4 è scritto in linguaggio C++ ed è costituito da una
gerarchia di classi.
L'unità base dell'Unreal Engine è il game object, istanza dalla classe
UObject. Questa classe rappresenta la base per qualsiasi entità che faccia
parte del mondo di gioco. Essa implementa, inoltre, i meccanismi di garbage collection, di serializzazione dei dati (data serialization) e di gestione dei
metadati.
Tra i più rilevanti game objects troviamo sicuramente gli actor, definiti come oggetti posizionabili e modificabili all'interno di un livello: le sedie, i tavoli, il sole, le pareti di una casa ed il personaggio giocante sono validi esempi di actor del sistema. Ciascun actor, oltretutto, può essere sottoposto alle canoniche trasformazioni tridimensionali di traslazione, rotazione e
scalatura. AActor è la classe di riferimento per tale speciale tipo di game
object.
Gli actor, inoltre, possono essere arricchiti tramite le cosiddette
components. Per component si intende una qualsiasi funzionalità o attributo
assegnabile ad un actor, il quale, tuttavia, non potrà mai esistere indipendentemente da esso; potremmo citare, ad esempio, l'audio del rumore
emesso da una sorgente sonora, oppure il comportamento fisico di un determinato actor.
Tra gli actor di maggior rilievo ricordiamo le pawn, istanze della classe Pawn. Una pawn è un particolare actor che rappresenta un avatar di gioco, sia esso un PC (Playable Character) oppure un NPC (Not Playable
Character).
I characters sono, altresì, particolari pawn, realizzate ad hoc per rappresentare personaggi direttamente gestiti dall'utente. Ecco perché la classe Character è munita, di base, di meccanismi di gestione delle collisioni e di movimento bipede.
Altri actors che vanno necessariamente citati sono i brush, istanze della classe Brush, semplicemente definibili come le geometrie fondamentali del mondo di gioco. Ci sono rette, piani, rettangoli, cubi, sfere, coni, ed in generale tutto il necessario per costruire qualsivoglia ambiente o architettura.
Quando un actor viene collocato nel mondo tridimensionale diviene parte di una scene, altrimenti detta level o map.
Una collezione di levels si definisce world e rappresenta l'intero mondo di gioco.
L'Unreal Engine 4 si compone di numerosi editor, tutti accessibili tramite la GUI dell'editor principale, preposti alle funzionalità più disparate:
Level Editor: è la base operativa del lavoro, fornisce una finestra sul mondo tridimensionale, consente di inserire nuovi attori nel mondo, di applicare ad essi trasformazioni di traslazione, rotazione e scalatura, così come di gestire l'illuminazione della scena. Dispone di un sistema di creazione e di manipolazione di geometrie. Consente, inoltre, di testare il proprio mondo 3D con la funzione
Material Editor: consente di creare nuovi materiali e di modificare quelli già esistenti;
Blueprint Editor: fornisce lo schema completo dei blueprints del
livello attuale, dando la possibilità di modificarlo a piacimento,
creando così nuove correlazioni tra gli attori;
Persona Editor: utilizzato per creare nuovi scheletri umani, mesh ed eleganti animazioni;
Niagara Editor: ha sostituito il precedente Cascade Editor, si tratta di un generatore di effetti speciali particellari;
UMG UI Editor: serve per creare i propri menu di gioco;
Matinee Editor: permette di creare e gestire cinematic di ogni tipo; SoundCue Editor: preposto a creazione e manipolazione di effetti
audio;
Paper2D Sprite Editor: serve a creare nuove sprite per i giochi 2D; Paper2D Flipbook editor: consente di creare animazioni per le
sprite 2D;
PhAT (Phisics Asset Tool): permette di gestire la fisica di gioco; Static Mesh Editor: consente di creare e modificare mesh statiche; Media Player Editor: dà la possibilità di gestire la riproduzione di
brani nel gioco;
2.1.3 PROGRAMMARE CON UNREAL
L'esperienza di programmazione con Unreal Engine 4 si potrebbe definire bipartita. Da un lato si trova il mondo delle classi C++, che costituiscono il nucleo del motore, mentre, dall'altro, si colloca il mondo dei nuovissimi blueprints. Per chi pensasse che lavorare con Unreal significhi operare una scelta tra uno stile di programmazione di serie A (C++) ed uno stile di serie B (blueprints) bisogna immediatamente specificare come i due sistemi siano stati creati allo scopo di interagire e compenetrarsi e non affatto per costituire uno un'alternativa dell'altro.
Il C++ di Unreal è ben lontano dal plain C++, infatti la quasi totalità delle funzionalità dell'engine si innescano e vengono invocate mediante un
sistema di tag appositamente creato dal team Unreal.
UPROPERTY() ed UFUNCTION() sono i due più lampanti esempi
di questa tecnica. Basta, quindi, anteporre ad una proprietà il primo tag e ad una funzione il secondo per trasformarle, rispettivamente, in una proprietà ed in una funzione del motore di gioco. Lo stesso ragionamento vale per
UCLASS, che trasforma una classe qualsiasi in una classe Unreal.
______________________________________________________________
UCLASS()
class AMyActor : public AActor
{ GENERATED_BODY() public: UPROPERTY(EditAnywhere) int32 TotalDamage; ... };
______________________________________________________________
Listato 2.1: Dichiarazione di una classe personalizzata che eredita da AActor in Unreal.
I parametri dei tag servono a specificare la modificabilità e la
visiblità dell'oggetto taggato rispetto agli editor di Unreal.
______________________________________________________________
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
int32 TotalDamage;
______________________________________________________________ Listato 2.2: Dichiarazione di una variabile di istanza e di una proprietà che sia ovunque modificabile ed
editabile per mezzo dei blueprints in Unreal.
E' possibile, quindi, rendere un oggetto visibile tramite editor, oppure rendere un valore modificabile (sia staticamente sia a runtime), così come esporre attributi e funzioni al meccanismo dei blueprint, nonché annotarli con un determinato tag.
Nella logica degli sviluppatori dell'Engine, lavorare con il C++ deve essere prerogativa solo dei programmatori più esperti, lasciando invece, ai
game designers, il compito di lavorare con la comoda interfaccia blueprint,
che consente di creare dinamiche di gioco pur non essendo in possesso di particolari capacità tecniche.
I blueprint non sono altro che un flessibile e potente linguaggio di
visual scripting che fornisce una schematica rappresentazione visiva a grafo dei game actor, delle component ad essi legate e delle relazioni che
intercorrono tra gli actor stessi. Il blueprint di un livello racchiude, qundi, i meccanismi di causa effetto che regolano il comportamento degli actor del livello stesso.
Se volessimo vedere, ad esempio, un braciere esplodere quando il personaggio giocante schiaccia una certa mattonella sul pavimento, potremmo agire così:
creiamo una trigger box e la collochiamo sulla mattonella scelta; creiamo una sorgente sonora e le associamo il rumore di una
esplosione;
cerchiamo e selezioniamo l'evento di collisione con il personaggio tra quelli disponibili per il trigger;
leghiamo all'evento di collisione la riproduzione di un suono dalla sopracitata sorgente sonora;
leghiamo all'evento di collisione la scomparsa del braciere.
Figura 2.43: Esempio di utilizzo dei blueprint. La scatola rossa rappresenta l'evento, quelle blu con la
lettera f sono le funzioni che vengono eseguite in risposta all'evento, mentre le altre blu sono gli oggetti bersaglio delle funzioni stesse.
Ecco che con pochi sforzi e senza scrivere una riga di codice, abbiamo implementato la nostra piccola idea. Nel prossimo capitolo vedremo più approfonditamente il funzionamento degli eventi di Unreal.
tra C++ e blueprint. Bisogna sfruttare il codice nativo per creare attori e, in generale, classi customizzate che soddisfino le nostre aspettative ed idee di gameplay.
In seguito è necessario servirsi della rapidità fornita dal comodissimo approccio visuale dei blueprint, che consentono di collegare tra loro i comportamenti di varie classi semplicemente linkandole in uno schema grafico.