Download scriptie
Download scriptie
Download scriptie
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
owered by TCPDF (www.tcpdf.org)<br />
Academiejaar 2012–2013<br />
Geassocieerde faculteit Toegepaste Ingenieurswetenschappen<br />
Valentin Vaerwyckweg 1 – 9000 Gent<br />
Onderzoek technologieën m.b.t. Rapid<br />
Game Prototyping<br />
Masterproef voorgedragen tot het behalen van het diploma van<br />
Master in de industriële wetenschappen: informatica<br />
Peter TIMMERMAN<br />
Promotoren: dr. Marleen DENERT<br />
Bernard FRANÇOIS (PreviewLabs)
owered by TCPDF (www.tcpdf.org)<br />
Academiejaar 2012–2013<br />
Geassocieerde faculteit Toegepaste Ingenieurswetenschappen<br />
Valentin Vaerwyckweg 1 – 9000 Gent<br />
Onderzoek technologieën m.b.t. Rapid<br />
Game Prototyping<br />
Masterproef voorgedragen tot het behalen van het diploma van<br />
Master in de industriële wetenschappen: informatica<br />
Peter TIMMERMAN<br />
Promotoren: dr. Marleen DENERT<br />
Bernard FRANÇOIS (PreviewLabs)
Woord vooraf<br />
Ter afsluiting van mijn masteropleiding in de Industriële Wetenschappen: Informatica<br />
schreef ik deze <strong>scriptie</strong>. Het onderwerp van deze masterproef handelt<br />
over een onderwerp dat mij al lange tijd zeer interesseert. Met deze<br />
masterproef had ik de mogelijkheid om de beginselen van game-development<br />
te leren, samen met een groot aantal verschillende technologieën, waarmee<br />
vernieuwende gameplay mogelijk was. Graag wil ik iedereen van het stagebedrijf<br />
bedanken, in het bijzonder Bernard François, voor de mogelijkheid om<br />
deze masterproef te doen. Ook dank aan de begeleiders van het stagebedrijf<br />
voor alle hulp tijdens de masterproef.<br />
Ook wil ik graag alle docenten bedanken. Hier wil zeker mijn interne<br />
promotor Marleen Denert bedanken voor de uitstekende begeleiding en hulp<br />
bij het schrijven van deze <strong>scriptie</strong>. Ik kon altijd bij haar terecht voor uitleg<br />
en advies.<br />
Tot slot wil ik mijn familie en vrienden bedanken voor alle steun en hulp.<br />
Dit heeft mij veel geholpen en het betekende veel voor mij. Mijn ouders wil<br />
ik zeker nogmaals bedanken, want zij hebben het mogelijk gemaakt voor mij<br />
om deze richting te volgen en hebben mij de hele weg gesteund.<br />
i
Inleiding<br />
Onderzoek<br />
PreviewLabs is een bedrijf dat zich specialiseert in Rapid Game Prototyping.<br />
Het doel van Rapid Game Prototyping is om snel en efficiënt een spel te kunnen<br />
maken waarmee gezien kan worden of de gameplay vernieuwend en leuk<br />
is. De term gameplay is een zeer ruim begrip. Het is één van de basiselementen<br />
van een videogame, naast onder andere de grafische aspecten en de<br />
audio. De gameplay bepaalt de manier waarop de gebruiker kan interageren<br />
met het spel en hoe verschillende uitdagingen overwonnen kunnen worden.<br />
Het is altijd een uitdaging om vernieuwende spellen te maken, zodat mensen<br />
het willen blijven spelen. Dit kan bereikt worden door een innovatieve gameplay<br />
te hebben in een spel. Als het spel makkelijk en aangenaam te spelen<br />
is en toch voor uitdaging kan zorgen zal men eerder dat spel spelen dan een<br />
spel dat weinig vernieuwing biedt.<br />
Dit onderzoek bestudeert enkele technologieën, die kunnen helpen bij Rapid<br />
Game Prototyping. Een aantal technologieën kunnen zorgen voor een snellere<br />
manier om bepaalde genres van prototypes te maken, zoals een tool die<br />
helpt om snel en makkelijk een race track te maken voor een race game. Voor<br />
andere technologieën moet onderzocht worden of ze die kan leiden tot een<br />
vernieuwende gameplay. Bijvoorbeeld de mogelijkheden onderzoeken van een<br />
API voor 3D-sensoren.<br />
Technologieën<br />
In deze paragraaf wordt beschreven welke technologieën onderzocht werden en<br />
welke vernieuwingen deze kunnen aanbrengen aan prototypes. Er wordt een<br />
korte beschrijving gegeven per technologie en er wordt gemotiveerd waarom<br />
sommige technologieën boven andere gekozen werden.<br />
Integratie Adobe Flash in Unity3D<br />
Animaties maken is makkelijker in Adobe Flash en voor game development is<br />
Unity3D een betere keuze. Tot niet zo lang geleden was er geen mogelijkheid<br />
ii
om Flash animaties te gebruiken in Unity, maar nu zijn er al enkele tools beschikbaar<br />
die de verbinding leggen tussen de twee. Drie hiervan zijn: uniSWF,<br />
Autodesk Scaleform en RAD Game Tools Iggy.<br />
Enkel uniSWF is speciaal ontworpen voor Unity. De andere twee tools zijn<br />
eerder integraties naar Unity van bestaande versies ervan. Op het eerste zicht<br />
zorgt uniSWF dat individuele movieclips van een Flash animatie in Unity<br />
beschikbaar zijn. Dit wil zeggen dat de functionaliteit met de animaties enkel<br />
beschikbaar is via de API van uniSWF, die gebruikt wordt in één van de<br />
scripttalen in Unity. Het lijkt er ook op dat alle ActionScript, die bij de<br />
animaties hoort, niet wordt uitgevoerd. Dit zorgt dat alle animaties enkel<br />
vanuit Unity, via de uniSWF API, kunnen gecontroleerd worden. Het voordeel<br />
hiervan is dat alle code binnen Unity gehouden wordt.<br />
Vervolgens zijn er Autodesk Scaleform en RAD Game Tools Iggy. Beide<br />
technologieën bestaan reeds voor een aantal andere platformen. Nu is ook<br />
voor deze technologieën een integratie voor Unity gemaakt. De basiswerking<br />
verloopt zeer gelijkaardig. De SWF-files worden als het ware over de camera<br />
in Unity gelegd en behouden al hun functionaliteit van ActionScript. Dit geeft<br />
dus vrijheid om code te verdelen tussen Unity en ActionScript. Er kunnen in<br />
beide richtingen berichten gestuurd worden, van Unity naar ActionScript en<br />
omgekeerd. Aangezien Iggy ook voor een periode gratis getest kon worden, is<br />
deze technologie verder onderzocht (zie Hoofdstuk 3: Integratie Adobe Flash<br />
in Unity3D).<br />
Accelerometer en gyroscope<br />
De accelerometer en gyroscope zijn twee sensoren, die te vinden zijn in de<br />
meeste smartphones. Hiermee zijn ook al verschillende soorten games gemaakt.<br />
Er is getest hoe deze twee sensoren gebruikt kunnen worden vanuit<br />
Unity en wat ze kunnen bieden voor nieuwe gameplay.<br />
Unity biedt zelf al een volledige interface aan om deze sensoren aan te<br />
spreken. Er is getest met een iPhone, aangezien de beschikbare Android devices<br />
enkel beschikten over een accelerometer en geen gyroscope (zie Hoofdstuk<br />
4: Accelerometer en gyroscope).<br />
Multiplayer racegame<br />
Een racegame bestaat uit twee belangrijke elementen: de wagen en de racetrack.<br />
Voor dit prototype werden een paar technologieën onderzocht, die<br />
kunnen helpen om snel en efficiënt een racetrack te creeëren, voor de wagen<br />
wordt gebruik gemaakt van een tutorial van Unity.<br />
Van de twee tools, die beschikbaar waren, is er gekozen voor de Road/Path<br />
tool van sixtimesnothing. Een andere tool, genaamd EasyRoads3D was een<br />
zeer goede tool om te gebruiken in de editor, maar er was te weinig vrijheid om<br />
dynamisch racetracks aan te maken via scripts. De GPS van een smartphone<br />
iii
kan gebruikt worden om punten voor de racetrack op te nemen. De Photonserver<br />
werd ook onderzocht. Dit bood een snelle implementatie van een<br />
lobbysysteem aan. Hiermee kan ook makkelijk een multiplayer gemplementeerd<br />
worden (zie Hoofdstuk 5: Multiplayer racegame).<br />
Brain Computer Interface<br />
Er zijn een aantal hardware-devices verschenen, die het mogelijk maken om<br />
hersengolven te meten. De Mindwave Mobile van Neurosky is daar één van. Er<br />
is voor de mobile versie gekozen, omdat deze ook compatibel is met smartphones.<br />
Deze device is gentegreerd in een Unity-project. Er is nagegaan hoe er<br />
met de device geconnecteerd wordt en hoe data opgehaald wordt. Vervolgens<br />
is getest of deze data bruikbaar was voor een nieuw soort gameplay in een<br />
prototype (zie Hoofdstuk 6: Brain Computer Interface).<br />
iv
Abstract<br />
Grotere game-development bedrijven hebben nood om op voorhand te weten<br />
of een nieuwe game kan aanslaan bij het grote publiek. Hiervoor is een leuke<br />
gameplay zeer belangrijk. Om nieuwe gameplay uit te testen worden prototypes<br />
gemaakt. Deze prototypes kunnen zeer snel gemaakt worden aangezien<br />
weinig tijd wordt besteed aan de grafische aspecten, foutafhandeling, speciale<br />
gevallen, ... . Er wordt voor de prototypes gewerkt in Unity3D.<br />
Voor een aantal technologieën werd onderzocht of deze kunnen bijdragen<br />
tot een vernieuwende gameplay. Sommige van de onderzochte technologieën<br />
moesten eerst nog geïntegreerd worden in Unity3D. Wanneer een technologie<br />
of meerdere technologieën samen aanleiding gaven tot een mogelijke nieuwe<br />
gameplay, is hiermee een prototype gemaakt.<br />
Er zijn twee technologieën onderzocht waarmee 2D-animaties van Adobe<br />
Flash gebruikt kunnen worden in Unity3D, uniSWF en Rad Game Tools: Iggy.<br />
De twee technologieën zijn met elkaar vergeleken om te weten te komen welke<br />
de beste resultaten gaf. Dit is gebeurd door een aantal simpele animaties te<br />
gebruiken in Unity.<br />
Er zijn tests uitgevoerd om de nauwkeurigheid van de accelerometer en<br />
gyroscope van een smartphone te testen. Hiermee is getest of het mogelijk<br />
is om enkel met deze twee sensoren de positie en oriëntatie in een ruimte te<br />
volgen.<br />
Er is een racegame prototype gemaakt met drie onderzochte technologieën.<br />
Het laat de gebruiker toe om dynamisch racetracks te maken met behulp van<br />
GPS-coördinaten, opgenomen met een smartphone. De coördinaten worden<br />
gebruikt met de Road/Path Tool om een racetrack te genereren in Unity. Ook<br />
werd er multiplayer-functionaliteit toegevoegd, met behulp van een photonserver.<br />
Als laatste zijn de mogelijkheden van een device, dat hersengolven kan<br />
meten, getest. Hiervoor is een integratie in Unity gemaakt en de meetwaarden<br />
zijn gebruikt in een Unity-prototype.<br />
v
Larger game-development companies have the need to know in advance<br />
whether a new game can appeal to the general public. A fun gameplay is<br />
very important for this. To test new gameplay, prototypes are made. These<br />
prototypes can be created very quickly since little time is spent on the graphic<br />
aspects, error handling, special cases, ... . The prototypes are created with<br />
Unity3D.<br />
A number of technologies were examined to check whether they could<br />
contribute to an innovative gameplay. Some of the investigated technologies<br />
had to be integrated into Unity3D. When a technology or multiple technologies<br />
together gave rise to a possible new gameplay, they were used in a prototype.<br />
Two technologies which allow the use of 2D-animations from Adobe Flash<br />
in Unity3D were examined, uniSWF and Rad Game Tools: Iggy. The two<br />
technologies were compared with each other to find out which gave the best<br />
results. This was done by using a number of simple animations in Unity.<br />
Tests have been conducted to check the accuracy of the accelerometer and<br />
gyroscope of a smartphone. This was examined by determining whether it is<br />
possible to determine the movement and orientation of the smartphone in a<br />
space, using these two sensors.<br />
A racing game prototype has been made with three investigated technologies.<br />
It allows the user to dynamically create racetracks using GPS<br />
coördinates, recorded with a smartphone. The coördinates are used with the<br />
Road / Path Tool to generate a racetrack in Unity. Multiplayer-functionality<br />
was added as well, using a photonserver.<br />
Lastly, the capabilities of a device that can measure brain-waves, were<br />
tested. An integration for Unity has been made for this and the readings were<br />
used in a Unity-prototype.
Inhoudsopgave<br />
Woord vooraf<br />
Inleiding<br />
Abstract<br />
Inhoudsopgave<br />
i<br />
ii<br />
vi<br />
viii<br />
1 Unity3D 1<br />
1.1 De Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
1.1.1 Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
1.1.2 Inspector . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
1.1.3 Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />
1.1.4 Projectstructuur . . . . . . . . . . . . . . . . . . . . . 3<br />
1.2 Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />
1.2.1 Editorscripts . . . . . . . . . . . . . . . . . . . . . . . 3<br />
1.2.2 Behaviourscripts . . . . . . . . . . . . . . . . . . . . . 5<br />
2 Integratie Adobe Flash in Unity3D 7<br />
2.1 Adobe Flash integratie . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.2 RAD Game Tools: Iggy . . . . . . . . . . . . . . . . . . . . . 8<br />
2.2.1 De trial . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.2.2 Werking . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.2.3 Conclusies Iggy . . . . . . . . . . . . . . . . . . . . . . 10<br />
2.3 uniSWF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
2.3.1 Conclusies uniSWF . . . . . . . . . . . . . . . . . . . . 13<br />
3 Accelerometer en gyroscope 14<br />
3.1 De accelerometer . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
3.2 De gyroscope . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />
3.3 Implementatie in Unity . . . . . . . . . . . . . . . . . . . . . . 16<br />
3.3.1 Positiebepaling . . . . . . . . . . . . . . . . . . . . . . 17<br />
3.3.2 Positiebepaling van een eenvoudige beweging . . . . . . 17<br />
3.3.3 Oriëntatiebepaling . . . . . . . . . . . . . . . . . . . . 20<br />
3.4 Conclusies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
vii
INHOUDSOPGAVE<br />
viii<br />
4 Multiplayer racegame 23<br />
4.1 Gebruik van Road/Path Tool . . . . . . . . . . . . . . . . . . 23<br />
4.1.1 De tool gebruiken in de editor . . . . . . . . . . . . . . 23<br />
4.1.2 Dynamisch gebruik . . . . . . . . . . . . . . . . . . . . 25<br />
4.2 Behandeling van GPS-coördinaten voor racetrack . . . . . . . 25<br />
4.2.1 GPS gebruiken in Unity . . . . . . . . . . . . . . . . . 26<br />
4.2.2 Verwerken GPS-coördinaten . . . . . . . . . . . . . . . 27<br />
4.3 Werking photonserver . . . . . . . . . . . . . . . . . . . . . . . 29<br />
4.3.1 De spelers . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.3.2 Lobby . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.3.3 Multiplayer . . . . . . . . . . . . . . . . . . . . . . . . 31<br />
4.4 Extra functionaliteit voor het prototype . . . . . . . . . . . . 33<br />
4.5 Conclusies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34<br />
5 Brain Computer Interface 35<br />
5.1 Werking Mindwave Mobile . . . . . . . . . . . . . . . . . . . . 35<br />
5.1.1 Connecteren met Mindwave Mobile . . . . . . . . . . . 35<br />
5.2 Integratie in Unity . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
5.3 Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
5.3.1 Conclusies . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
Besluit 38<br />
Literatuurlijst 40<br />
A Unity3D Sceneview 41<br />
B Unity3D Gameview 43
Hoofdstuk 1<br />
Unity3D<br />
Previewlabs gebruikt voor het maken van prototypes meestal Unity3D. Dit is<br />
een 3D game-engine waarmee video-games, zowel 3D als 2D, voor consoles,<br />
smartphones of voor het web gemaakt kunnen worden. In dit hoofdstuk wordt<br />
kort de basisfunctionaliteit van Unity uitgelegd. Unity bestaat uit twee grote<br />
delen: de editor en scripting. In de editor worden alle gameobjecten klaargezet<br />
en worden er scripts aan toegewezen. In de scripts wordt geprogrammeerd hoe<br />
de objecten reageren op bepaalde events en wordt het algemene gedrag van<br />
de objecten bepaald.<br />
1.1 De Editor<br />
1.1.1 Scene<br />
Het eerste onderdeel van de editor is de scene. Dit is de 3D-ruimte waarin<br />
verschillende gameobjecten geplaatst kunnen worden. Hierin komen alle objecten,<br />
die niet dynamisch worden aangemaakt. Een belangrijk object is de<br />
main camera. Dit object is bijna altijd aanwezig in een scene. Het kan ook<br />
dynamisch worden aangemaakt, maar als het in de scene wordt gezet, kan<br />
men overschakeling op de Game view, waarmee een preview te zien is van wat<br />
de camera ziet en wat dus ook de speler te zien krijgt.<br />
1.1.2 Inspector<br />
Een tweede onderdeel is de inspector. Deze toont de eigenschappen van elk<br />
object, deze worden achter de schermen gestuurd door scripts. Elk object in<br />
de scene beschikt over de transform eigenschap. Hiermee wordt de translatie,<br />
rotatie en schaal van het object in drie dimensies bepaald. Er zijn nog veel<br />
meer eigenschappen, die bij bepaalde soorten objecten horen. Een lichtbron<br />
heeft de light eigenschap, 3D-objecten hebben een mesh, een collider en een<br />
renderer. De mesh bepaalt de vorm van het voorwerp, Unity heeft een aantal<br />
standaard vormen zoals een kubus, een bol, een cilinder,... . Een mesh is niets<br />
1
HOOFDSTUK 1. UNITY3D 2<br />
meer dan een aantal driehoeken, die samen een complex 3D-voorwerp kunnen<br />
vormen.<br />
Figuur 1.1: Een bol en kubus in Unity<br />
In Unity wordt een mesh voorgesteld als een lijst met punten, de hoekpunten<br />
van alle driehoeken, en een lijst die telkens drie punten verbindt tot<br />
een driehoek. Onderstaande code maakt een vierkante mesh.<br />
Mesh mesh = new Mesh();<br />
//Hier worden de vier hoekpunten aangeduid<br />
mesh.vertices = [new Vector3{0,0,0},new Vector3{0,1,0}<br />
,new Vector3{1,1,0},new Vector3{1,0,0}];<br />
/*Nu worden hoekpunten verbonden tot driehoeken<br />
*Deze tabel heeft als grootte altijd een veelvoud van drie<br />
*De eerste driehoek verbindt de eerste drie hoekpunten uit<br />
*bovenstaande tabel<br />
*De tweede verbindt de laatste twee en het eerste hoekpunt<br />
*/<br />
mesh.triangles = [0,1,2,2,3,0];<br />
Het is al snel duidelijk dat meer complexe voorwerpen, die al snel honderden<br />
driehoekjes kunnen bevatten, beter niet op deze manier gemaakt worden.<br />
Hiervoor bestaan verschillende softwareproducten waar dit in een 3D-ruimte<br />
kan gebeuren zoals Blender, Autodesk 3DSMax en Cinema4D.<br />
Een collider bepaalt of het voorwerp als Trigger functioneert en uit welk fysiek<br />
materiaal het bestaat. Waar de mesh de vorm bepaalt van het voorwerp,<br />
daar bepaalt de collider hoe het voorwerp fysiek met de omgeving reageert.<br />
Een extreem voorbeeld is om een object met een bolvormige mesh een kubusvormige<br />
collider te geven. Dit zorgt dat het object eruit ziet als een bol,<br />
maar hij zal niet rollen omdat het fysiek op een kant van de kubus ligt. Als<br />
het object als trigger gebruikt wordt, dan is dit om events af te handelen.<br />
Het wordt niet meer als fysiek object beschouwd waartegen andere objecten<br />
kunnen botsen. De trigger zal events afvuren voor andere colliders die de
HOOFDSTUK 1. UNITY3D 3<br />
trigger binnenkomen, buitengaan of die zich in de trigger bevinden. De meest<br />
gebruikte methodes zijn: OnTriggerEnter, OnTriggerExit en OnTriggerStay.<br />
Een gewoon fysiek object, dat niet als trigger gebruikt wordt, heeft ook<br />
een fysiek materiaal. Dit bepaalt onder andere de wrijving en de veerkracht.<br />
De renderer hoort samen met de mesh, hiermee wordt bepaald of het<br />
voorwerp al dan niet schaduwen veroorzaakt en zelf schaduwen krijgt. De<br />
texture van het voorwerp wordt ook bepaald.<br />
1.1.3 Hierarchy<br />
Vervolgens is er de hierarchy. Dit is een lijst van alle objecten die zich in<br />
de scene bevinden. Als het spel in Unity getest wordt, bevat de lijst ook<br />
dynamische objecten. Hierin kunnen verschillende objecten samengenomen<br />
worden tot één geheel. Bijvoorbeeld als men alle onderdelen van een auto<br />
(wielen, ruiten, enz.) als objecten heeft, dan kunnen deze allemaal onder<br />
één object gebracht worden. De onderdelen behouden hun relatieve positie<br />
ten opzichte van het algemene object. Zo kan het nieuwe object in de scene<br />
verplaatst worden, zonder dat elk apart onderdeel verplaatst moet worden.<br />
1.1.4 Projectstructuur<br />
Als laatste is er naast de hierarchy een mappenstructuur van het project te<br />
vinden. Hierin zijn alle Assets van het project te vinden. Dit houdt in: alle<br />
scripts, objecten, materials, textures, scenes, audio, ... . Nog iets belangrijk<br />
dat in deze structuur te vinden is, zijn de prefabs. Prefabs worden gemaakt<br />
door een object uit de hierarchy in de mappenstructuur te slepen, meestal<br />
onder Resources/Prefabs. Dit object kan nu verwijderd worden uit de hierarchy<br />
en dynamisch aangemaakt worden. Dit komt ongeveer neer op een klasse<br />
maken van het object, waarvan tijdens de applicatie dynamisch verschillende<br />
clonen aangemaakt kunnen worden met dezelfde eigenschappen.<br />
1.2 Scripting<br />
Unity werkt achter de schermen via scripts. Unity beschikt over JavaScript,<br />
BooScript en C#. Voorbeelden in deze <strong>scriptie</strong> gebruiken C#, tenzij het<br />
anders vermeld wordt. De functionaliteit kan ook uitgebreid worden met<br />
behulp van plugins. Dit zijn native code bibliotheken, geschreven in C of C++,<br />
waarvan functies opgeroepen kunnen worden vanuit scripts. De scripts kunnen<br />
onderverdeeld worden in twee soorten, editorscripts en behaviourscripts.<br />
1.2.1 Editorscripts<br />
Deze scripts zijn in Unity vooral op de achtergrond aanwezig. De hele editor<br />
werkt achter de schermen met editorscripts. Deze scripts zijn afgeleid van de
HOOFDSTUK 1. UNITY3D 4<br />
klasse EditorWindow. Hiermee kan men de editor extra functionaliteit geven.<br />
Editorscripts worden meestal gebruikt om objecten meer eigenschappen te<br />
geven die dan makkelijk vanuit de editor aan te passen zijn. Er kan gebruik<br />
gemaakt worden van toggle buttons, sliders, text fields, ... . Het script zal<br />
dan bij aanpassing van deze velden de nodige variabelen kunnen aanpassen.<br />
Een voorbeeldje van de Unity website.<br />
using UnityEditor;<br />
using UnityEngine;<br />
public class MyWindow : EditorWindow<br />
{<br />
string myString = "Hello World";<br />
bool groupEnabled;<br />
bool myBool = true;<br />
float myFloat = 1.23f;<br />
// Add menu item named "My Window" to the Window menu<br />
[MenuItem("Window/My Window")]<br />
public static void ShowWindow()<br />
{<br />
//Show existing window instance.<br />
//If one doesn’t exist, make one.<br />
EditorWindow.GetWindow(typeof(MyWindow));<br />
}<br />
void OnGUI()<br />
{<br />
GUILayout.Label ("Base Settings",<br />
EditorStyles.boldLabel);<br />
myString = EditorGUILayout.TextField ("Text Field",<br />
myString);<br />
groupEnabled = EditorGUILayout.BeginToggleGroup (<br />
"Optional Settings", groupEnabled);<br />
myBool = EditorGUILayout.Toggle ("Toggle", myBool);<br />
myFloat = EditorGUILayout.Slider ("Slider", myFloat,<br />
-3, 3);<br />
EditorGUILayout.EndToggleGroup ();<br />
}<br />
}<br />
Dit geeft volgend editor venster.
HOOFDSTUK 1. UNITY3D 5<br />
Figuur 1.2: Een eigengemaakt editorvenster<br />
Hier is de koppeling te zien tussen de GUI-elementen en variabelen. Wanneer<br />
de gebruiker het tekstveld aanpast wordt de variabele myString automatisch<br />
aangepast. Tegelijk wordt deze variabele gebruikt om de huidig ingevulde<br />
waarde te tonen in het tekstveld. Er is dus geen nood om telkens te kijken<br />
of de gebruiker het tekstveld heeft aangepast en vervolgens de waarde op te<br />
vragen.<br />
1.2.2 Behaviourscripts<br />
Deze scripts zorgen voor functionaliteit terwijl de applicatie loopt. Ze zijn<br />
afgeleid van MonoBehaviour en worden altijd verbonden met een object. In<br />
de inspector van een object zijn alle eraan verbonden scripts te zien. Het<br />
object waaraan het script verbonden is kan aangesproken worden via game-<br />
Object. Hiermee kan bijvoorbeeld de transform eigenschap ervan aangepast<br />
worden. De scripts werken event-gebaseerd. Enkele belangrijke methodes,<br />
die in de meeste applicaties gebruikt worden zijn: Start, Awake, Update en<br />
FixedUpdate.<br />
De Awake en Start functie kunnen gebruikt worden voor initialisatie. Het<br />
verschil ligt hem in het moment van oproepen. Alle Awake methodes worden<br />
voor alle Start methodes uitgevoerd, zodat alle nodige initialisaties uitgevoerd<br />
zijn. Awake wordt uitgevoerd wanneer een instantie gemaakt wordt. Start<br />
wordt pas opgeroepen vlak voor de eerste keer dat één van de update methoden<br />
wordt opgeroepen. Dit laat toe om extra initialisaties te doen net voor het<br />
echt nodig is. Als een script afgezet wordt in de editor, dan wordt Start niet<br />
uitgevoerd, maar Awake wel.<br />
Update en FixedUpdate zijn beide methodes die telkens na een tijdsinterval<br />
uitgevoerd worden. Update activeert één keer per frame. Hierdoor is het<br />
tijdsinterval tussen twee Updates niet constant, het aantal frames per seconde<br />
is namelijk niet constant. Deze methode wordt gebruikt om het meeste gedrag<br />
van de applicatie te implementeren. Hier kan bijvoorbeeld de eigenschap<br />
transform aangepast worden.
HOOFDSTUK 1. UNITY3D 6<br />
public class Foo : MonoBehaviour {<br />
void Update() {<br />
gameObject.transform.Translate(Time.deltaTime*1f,0f,0f);<br />
}<br />
}<br />
Deze code zal het gameobject in de x-richting bewegen aan één unit per seconde.<br />
Time.deltaTime geeft de tijd in seconden sinds de laatste Update.<br />
FixedUpdate wordt telkens na een vast tijdsinterval opgeroepen. Dit wordt<br />
gebruikt voor physics. Physics bepalen hoe een object reageert op krachten,<br />
zoals zwaartekracht en botsingen met andere objecten. Unity beschikt over<br />
een Rigidbody om objecten physics te geven, maar dit kan ook zelf in een<br />
script gedaan worden. Aangezien de rigidbody de positie van het object kan<br />
aanpassen aan de hand van krachten die erop uitgevoerd worden en aangezien<br />
de berekening van positieverandering op discrete tijdstippen gebeurt, moeten<br />
aanpassingen aan de rigidbody ook op discrete tijdstippen gebeuren. Hiervoor<br />
is de FixedUpdate nodig.<br />
void FixedUpdate() {<br />
rigidbody.AddForce(new Vector3(10f,0f,0f));<br />
}<br />
Bovenstaande code oefent een kracht uit op de rigidbody, het gameobject<br />
waaraan de rigidbody hangt zal hierdoor bewegen. De rigidbody bepaalt ook<br />
de massa van het object waarmee de kracht kan omgezet worden in versnelling<br />
en leidt verder tot de verplaatsing van het object.<br />
Unity biedt nog veel meer functionaliteit en hierover is zeer veel documentatie<br />
ter beschikking.
Hoofdstuk 2<br />
Integratie Adobe Flash in<br />
Unity3D<br />
Unity biedt veel mogelijkheden aan voor de creatie van een 3D-omgeving,<br />
maar heeft geen uitgebreid animatiesysteem. Er is een systeem beschikbaar<br />
om basis animaties te creeëren, maar dit wordt overtroefd door vele andere<br />
technologieën die speciaal hiervoor ontworpen zijn. Eén van deze is Adobe<br />
Flash.<br />
2.1 Adobe Flash integratie<br />
Adobe Flash is software gespecialiseerd in het maken van 2D-animaties. Het<br />
wordt voornamelijk gebruikt in webtoepassingen en bij game-development.<br />
Flash files hebben een ShockWave Flash(SWF) formaat. Om Flash applicaties<br />
te gebruiken in een webbrowser is er nood aan een Flash Player plugin.<br />
In tegenstelling tot de animatiemogelijkheden in Unity beschikt Flash over<br />
een veel uitgebreider pakket aan mogelijkheden. Hiermee kunnen veel natuurlijkere<br />
en meer complexe animaties gemaakt worden. Een animatie is niets<br />
meer dan een opeenvolging van stilstaande beelden, ook wel frames genoemd.<br />
De programmatie in Flash, wat de opeenvolging van alle frames bepaalt, wordt<br />
gedaan met behulp van de tijdlijn en een scripttaal, Actionscript. De tijdlijn<br />
is opgedeeld in een aantal korte tijdstappen waarin telkens een frame kan geplaatst<br />
worden. Er kan bepaald worden hoeveel frames per seconde worden<br />
getoond. Als deze snelheid te laag ligt, verloopt de animatie zeer schokkerig.<br />
Als de snelheid te hoog ligt gaat men veel meer frames nodig hebben om dezelfde<br />
speelduur van de animatie te halen en de kwaliteit is niet noodzakelijk<br />
beter. De tijdlijn laat ook toe om meerdere van deze animaties tegelijk te<br />
spelen en te bepalen welke animatie op de voorgrond blijft als ze zouden overlappen.<br />
ActionScript is een object-georiënteerde scripttaal, sterk beïnvloed<br />
door JavaScript, maar met uitgebreidere functionaliteit om te werken met<br />
animaties. Het werkt event-gebaseerd, er worden dus acties uitgevoerd wanneer<br />
bepaalde events optreden, zoals het starten van de ene animatie en het<br />
7
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 8<br />
stoppen van een andere. Voor animaties kan voornamelijk de tijdlijn gebruikt<br />
worden, maar bij game-development is er nood aan programmatie in ActionScript.<br />
Aangezien Unity een betere applicatie is voor game-development, maar<br />
minder voor animaties en Flash net het omgekeerde, zou het zeer handig zijn<br />
om de twee te kunnen combineren. Dit ging vroeger niet zomaar, maar nu zijn<br />
er enkele technologieën die een brug kunnen vormen tussen Flash en Unity. In<br />
de volgende paragrafen wordt RAD Game Tools: Iggy besproken, vervolgens<br />
wordt kort nog uniSWF besproken.<br />
2.2 RAD Game Tools: Iggy<br />
RAD Game Tools is een groep die een grote hoeveelheid tools aanbiedt voor<br />
game developers, zoals bijvoorbeeld Bink Video. De tools worden speciaal<br />
ontworpen voor developers en zijn makkelijk in gebruik. Iggy is een tool voornamelijk<br />
gemaakt om User Interfaces, gemaakt in Flash, te kunnen gebruiken<br />
op andere platformen, maar kan ook andere soorten SWF-files aan. Het doel<br />
van Iggy is om een scheiding aan te brengen tussen de artistieke kant, het maken<br />
van animaties, en de programmatorische kant, hetgeen alles stuurt. Iggy<br />
heeft ook recent de mogelijkheid toegevoegd voor een integratie van Flash in<br />
Unity. Hiermee wordt het mogelijk om SWF-files te gebruiken in Unity.<br />
2.2.1 De trial<br />
Er was een mogelijkheid om deze tool te testen voor een aantal dagen met<br />
een trial. Helaas was deze trial eigenlijk een voorbeeldproject waarmee enkele<br />
verschillende animaties konden afgespeeld worden op de scene in Unity. Hier<br />
was ook nog de beperking dat enkel de functies, die geïmporteerd werden uit de<br />
dll’s gebruikt konden worden. Een uitgebreide documentatie was ook afwezig,<br />
er werd enkel hier en daar commentaar toegevoegd om bepaalde stappen uit<br />
te leggen.<br />
2.2.2 Werking<br />
In de volgende paragrafen wordt de werking van Iggy uitgediept en hoe de<br />
programmatie eerder in ActionScript kan plaatsvinden of eerder in Unity.<br />
Bij de start van de applicatie wordt Iggy geïnitialiseerd. In deze procedure<br />
wordt onder andere ingesteld hoe de rendering van Flash content moet<br />
gebeuren en hoeveel resources hiervoor worden toegewezen. Ook wordt gezorgd<br />
dat audio van de Flash file doorgegeven wordt aan een Audiodevice.<br />
Vervolgens wordt de renderqueue aangemaakt waarin alle animaties komen<br />
die gerendered moeten worden. Als laatste worden alle SWF-files omgezet in<br />
een Iggy-formaat.<br />
StringBuilder errorString = new StringBuilder(256);
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 9<br />
Iggy.IggyResult result = new Iggy.IggyResult();<br />
Iggy.IggyPlayerConfig config = new Iggy.IggyPlayerConfig();<br />
Movie = Iggy.IggyPlayerCreateFromFileAndPlay(<br />
"Assets/basic_animation.swf", ref config,<br />
ref result, errorString, errorString.MaxCapacity);<br />
Na deze initialisatie worden alle Unity keycodes gemapt op Iggy keycodes.<br />
Deze worden gebruikt om events tussen Unity en Flash te sturen. Als laatste<br />
wordt een routine gestart die telkens wacht tot het einde van een frame in<br />
Unity.<br />
yield return StartCoroutine("CallPluginAtEndOfFrames");<br />
Hierna loopt de applicatie en worden er berichten heen en weer gestuurd op<br />
vaste momenten. Er zijn twee momenten waarop berichten gestuurd worden.<br />
Het eerste is wanneer er GUI-events plaatsvinden, hieronder vallen keyup, keydown,<br />
mouseup en mousedown events. Deze events kunnen meerdere keren<br />
per frame voorkomen. Wanneer zo’n event plaatsvindt wordt de keycode omgezet<br />
naar Iggy-formaat en kan zo doorgestuurd worden naar de ActionScript<br />
van een bepaalde SWF-file. Hier gebeurt dan de normale event-handling.<br />
Event e = Event.current;<br />
if (e.type == EventType.MouseDown && e.button == 0)<br />
{<br />
Iggy.IggyEvent mouseEvent = new Iggy.IggyEvent();<br />
Iggy.IggyMakeEventMouseButton(ref mouseEvent,<br />
Iggy.IggyMousebutton.<br />
IGGY_MOUSEBUTTON_LeftDown);<br />
Iggy.IggyEventResult event_result =<br />
new Iggy.IggyEventResult();<br />
Iggy.IggyPlayerDispatchEventRS(Movie, ref mouseEvent,<br />
ref event_result);<br />
}<br />
Het tweede moment dat berichten gestuurd worden is op het einde van een<br />
frame. Eerst worden alle animaties toegevoegd aan de renderqueue, zelfs al<br />
moeten deze animaties niet afgespeeld worden die frame. Er wordt ook per<br />
animatie, die afgespeeld moet worden, een displaysize gezet. Dit zorgt er voor<br />
dat de animatie eigenlijk over het camerabeeld geplakt wordt. Hierna kunnen<br />
de variabelen van het ActionScript van een animatie bekeken en aangepast<br />
worden. Op het einde van deze routine kan men de gewenste animaties ook<br />
een frame verder laten afspelen.<br />
while(true)<br />
{<br />
yield return new WaitForEndOfFrame();
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 10<br />
}<br />
IggyUnityRenderQueueAdd(Movie);<br />
Iggy.IggyPlayerSetDisplaySize(Movie,<br />
Screen.width,<br />
Screen.height);<br />
while (Iggy.IggyPlayerReadyToTick(Movie))<br />
{<br />
Iggy.IggyValuePath root =<br />
Iggy.IggyPlayerRootPath(Movie);<br />
int foo = 10;<br />
Iggy.IggyValueSetS32RS(ref root, 0, "foo", foo);<br />
int bar;<br />
uint_bar = Iggy.IggyPlayerCreateFastName(Movie,<br />
"bar", 3);<br />
Iggy.IggyValueGetS32RS(ref root, uint_bar,<br />
IntPtr.Zero, ref bar);<br />
}<br />
Een groot voordeel van Iggy is dat je de keuze krijgt om de programmatie<br />
gedeeltelijk in ActionScript te doen of volledig in Unity te houden. Men kan<br />
in het eerste geval één grote SWF-file maken waar nog veel functionaliteit<br />
en event-handling gebeurt. Hierdoor worden voornamelijk de GUI-events in<br />
Unity doorgestuurd naar ActionScript, zodat daar de afhandeling kan plaatvinden.<br />
De tweede manier probeert om helemaal geen ActionScript meer te<br />
hebben en in plaats daarvan gebruik te maken van meerdere animaties. Deze<br />
verschillende animaties spelen dan afhankelijk van de gebeurtenissen in Unity<br />
al dan niet af. Even ter illustratie, men heeft een personage dat wandelt<br />
wanneer een pijltoest wordt ingedrukt en anders stilstaat. Hiervoor is er een<br />
wandelanimatie en een stilstaande animatie. De wandelanimatie zal enkel afspelen<br />
als men een pijltoest ingedrukt houdt en anders zal enkel de stilstaande<br />
animatie getoond worden. Deze methode is zeer nuttig als men een duidelijke<br />
scheiding wil tussen animatie en programmatie.<br />
Bij het stoppen van de applicatie moeten ook alle animaties en de renderqueue<br />
gestopt worden.<br />
2.2.3 Conclusies Iggy<br />
Beide methoden van programmatie werden getest. De eerste methode was<br />
zeer makkelijk in werking te krijgen, maar dit vereist dat de programmeur<br />
de animatie kan maken, in ActionScript en Unity programmeren. Het einddoel<br />
was om alle ActionScript te kunnen verwijderen. Dit is jammer genoeg<br />
niet helemaal gelukt. Er was geen duidelijke API om bepaalde animaties<br />
te starten, stoppen, te herstarten of gewoon naar een bepaalde frame springen.<br />
De verklaring hiervoor is waarschijnlijk dat het voorbeeldproject niet<br />
de hele interface ter beschikking stelt. Hierin was telkens maar één animatie
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 11<br />
die bleef afspelen. Pogingen om toch de animaties te laten afwisselen resulteerden<br />
meestal in een crash van Unity. Nadat een volledige omschrijving<br />
van het probleem per mail was gemeld aan de support bij het project, bleek<br />
het ook in hun geval te crashen. Hierdoor is ook gekozen om toch een kleine<br />
hoeveelheid te programmeren in ActionScript. Het uiteindelijke prototype<br />
kon meerdere animaties tegelijk afspelen waarbij sommige events naar de ene<br />
animatie werden gestuurd en andere events naar een tweede animatie.<br />
Iggy slaagt erin om Flash animaties af te spelen in Unity en biedt de<br />
vrijheid om de programmatie te verdelen tussen Unity en ActionScript, maar<br />
er zijn hier en daar nog wel bugs te vinden. De reden dat Iggy nog niet<br />
optimaal werkt ligt voornamelijk aan het feit dat de Unity integratie nog<br />
maar heel recent is en dus nog wat kinderziektes heeft.<br />
2.3 uniSWF<br />
UniSWF is een plugin, waarmee Flash-animaties geëxporteerd worden naar<br />
Unity. De animaties kunnen vervolgens aangesproken worden in Unity. Een<br />
eerste belangrijk aspect van uniSWF is dat SWF-files vanuit Flash geconverteerd<br />
worden naar een MovieClip. Via de aangeboden interface van uniSWF<br />
kunnen deze objecten aangesproken worden vanuit Unity. Dit is de enige<br />
manier om de animaties te controleren, aangezien alle programmatie in ActionScript<br />
niet gebruikt kan worden. De programmatie wordt nu enkel in Unity<br />
gehouden.<br />
De nuttigste methoden van deze interface zijn Play, Stop en GotoAndPlay.<br />
De eerste twee zijn vanzelfsprekend, de derde methode start een animatie van<br />
een bepaalde frame, de framenummer wordt als parameter meegegeven.<br />
De movieclips worden niet zomaar gebruikt, maar ze worden gekoppeld<br />
aan een behaviour. UniSWF voegt enkele nieuwe behaviours toe, die aan gameobjecten<br />
gekoppeld worden. Deze behaviours kunnen movieclips bevatten.<br />
De twee belangrijkste zijn MovieClipBehaviour en<br />
MovieClipOverlayCameraBehaviour. De eerste behaviour wordt gebruikt<br />
om een animatie als gameobject in Unity te hebben. Dit kan gebruikt worden<br />
voor personages met een wandelanimatie. Het gameobject kan zoals elk<br />
ander object bewogen worden, het enige wat hierbij nog extra moet gebeuren<br />
is zorgen dat de animatie afspeelt en stopt op de juiste momenten. Hiermee<br />
kunnen veel verschillende bewegingen in één animatie gemaakt worden, bijvoorbeeld<br />
een wandelanimatie en een spronganimatie kunnen in één grotere<br />
animatie zitten. Als er gesprongen wordt, kan de animatie afgespeeld worden<br />
vanaf het frame waar de spronganimatie start.<br />
MovieClip character;<br />
MovieClipBehaviour behav = (MovieClipBehaviour)<br />
gameObject.GetComponent("MovieClipBehaviour");<br />
character = behav.movieClip;
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 12<br />
if(Input.GetKey(KeyCode.LeftArrow))<br />
{<br />
if(character.currentFrame >= 25 &&<br />
character.currentFrame < 47)<br />
character.play();<br />
else{<br />
character.gotoAndPlay(25);<br />
}<br />
gameObject.transform.Translate(new Vector3(-0.005f,0f,0f));<br />
}<br />
In bovenstaande code wordt de movieclip opgehaald van de movieclipbehaviour.<br />
Als de linkerpijltoest ingedrukt is, wordt de animatie afgespeeld tussen<br />
frame 25 en 47. Dit is een animatie van een personage die naar links wandelt,<br />
het gameobject waaraan de animatie gekoppeld is wordt dan ook verplaatst<br />
naar links.<br />
De tweede behaviour, MovieClipOverlayCameraBehaviour, is zeer goed<br />
te vergelijken met wat gebeurde in Iggy. Dit behaviour wordt met de camera<br />
gekoppeld. De animaties worden hierbij bovenop het camerabeeld geplaatst,<br />
dit is dus meer geschikt voor menu’s en dergelijke. De interface van de behaviour<br />
doet sterk denken aan java swing.<br />
stage = MovieClipOverlayCameraBehaviour.instance.stage;<br />
MovieClip btn = new MovieClip("swf/button_asset.swf:btn_ui");<br />
btn.x = 420;<br />
btn.y = 300;<br />
btn.gotoAndStop(1);<br />
btn.addEventListener( MouseEvent.CLICK, onButtonClick);<br />
btn.addEventListener( MouseEvent.ENTER, onButtonEnter);<br />
stage.addChild(btn);<br />
...<br />
void onButtonEnter(CEvent e) {<br />
MovieClip m = e.currentTarget as MovieClip;<br />
m.gotoAndStop(2);<br />
}<br />
Er kunnen verschillende animaties toegevoegd worden, elk met een positie<br />
en eventlisteners. In deze code wordt een knop toegevoegd, deze heeft maar<br />
twee frames, één waar de knop is opgelicht en één waar hij niet is opgelicht.<br />
Met de events wordt gereageerd wanneer de gebruiker met de cursor over de<br />
knop gaat. De juiste frame van de animatie wordt getoond.
HOOFDSTUK 2. INTEGRATIE ADOBE FLASH IN UNITY3D 13<br />
2.3.1 Conclusies uniSWF<br />
Hier wordt nog een korte vergelijking met Iggy beschreven als besluit. UniSWF<br />
was veel makkelijker te begrijpen en te gebruiken dan Iggy. Het biedt de nodige<br />
interface aan om met verschillende animaties te werken. Eën van de<br />
voornaamste verschillen ligt hem in de verdeling van code. Waar Iggy de<br />
programmatie kon verdelen tussen ActionScript en Unity, wordt nu alle programmatie<br />
op één plaats gehouden, namelijk binnen Unity. Een ander verschil<br />
lag hem in het makkelijk controleren van animaties. UniSWF bood een makkelijke<br />
interface aan om animaties te starten, stoppen en naar bepaalde frames<br />
te spring, maar bij Iggy was dit echter niet zo makkelijk te verwezenlijken.
Hoofdstuk 3<br />
Accelerometer en gyroscope<br />
Er bestaan verschillende manieren om de accelerometer en gyroscope te gebruiken<br />
in een game. Enkele voorbeelden: de accelerometer gebruiken voor<br />
een tilting game of de gyroscope gebruiken om de camera te rotereren.<br />
Figuur 3.1: Een bekende tilting game<br />
Er is geprobeerd om de rotatie en positie van een smartphone te volgen in<br />
Unity aan de hand van data verkregen van de accelerometer en de gyroscope.<br />
Het uiteindelijke doel was om hiermee het gevolgde pad van de smartphone in<br />
een ruimte te recreeëren met een mesh in Unity. Deze vorm zou uiteindelijk<br />
geprojecteerd worden op het scherm van de smartphone op de juiste plek in de<br />
ruimte. Theoretisch is dit mogelijk met de gegeven sensoren, praktisch blijkt<br />
het toch niet helemaal mogelijk. Eerst worden de twee sensoren besproken en<br />
vervolgens de aanpak en welke moeilijkheden in de praktijk opduiken.<br />
3.1 De accelerometer<br />
Dit is een sensor die acceleraties meet. Hieronder vallen acceleraties afkomstig<br />
van de zwaartekracht en acceleraties door beweging. Zwaartekracht zorgt voor<br />
een constante acceleratie van 1g (9.81m/s) verdeeld over de drie assen. Dit<br />
kan berekend worden als de hoek tussen de accelerometer en de zwaartekracht<br />
bekend is.<br />
14
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 15<br />
Figuur 3.2: Zwaartekracht op de smartphone<br />
Dit wordt in smartphones gebruikt om de oriëntatie te bepalen. Hierbij<br />
wordt via de accelerometer gekeken langs welke as de zwaartekracht ligt om<br />
zo het scherm juist te oriënteren. De accelerometer meet ook acceleraties<br />
veroorzaakt door beweging. Deze acceleraties kunnen gebruikt worden om de<br />
snelheid en vervolgens de verplaatsing te bepalen.<br />
3.2 De gyroscope<br />
Deze sensor wordt gebruikt om oriëntatie te bepalen. Een gyroscope is een<br />
object dat om zijn eigen as draait, het is eigenlijk een gewone tol.<br />
Figuur 3.3: Een mechanische gyroscope<br />
Als de gyroscope draait om zijn as, onstaat er een impulsmoment. Dit<br />
zorgt ervoor dat de gyroscope zijn huidige oriëntatie blijft behouden. Hierdoor<br />
valt een draaiende tol niet om. Wanneer een gyroscope wordt gebruikt in een<br />
Cardanische ophanging, dit zijn de metalen ringen op de bovenstaande figuur,<br />
kan de oriëntatie bepaald worden van een object waaraan de buitentste ring<br />
vasthangt, bijvoorbeeld een vliegtuig. Dit is mogelijk aangezien de ringen vrij<br />
in drie dimensies kunnen bewegen rond de gyroscope en deze zal zelf, door<br />
zijn draaiing, altijd dezelfde oriëntatie behouden. Deze drie dimensies worden<br />
uitgedrukt in roll, pitch en yaw.
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 16<br />
Figuur 3.4: De drie draaibewegingen<br />
De drie draaihoeken worden ook wel Euler-hoeken genoemd.<br />
3.3 Implementatie in Unity<br />
In Unity kunnen accelerometer- en gyroscopewaarden opgehaald worden via<br />
volgende code.<br />
Vector3 acceleratie = Input.acceleration;<br />
Gyroscope gyro = Input.gyro;<br />
De eerste lijn geeft de acceleratie volgens de x,y en z as terug. De invloed<br />
van de zwaartekracht wordt ook gemeten. Aangezien de accelerometer onafhankelijk<br />
van Unity meetwaarden teruggeeft, kan het voorkomen dat er geen,<br />
één of meerdere nieuwe acceleraties gemeten zijn in een frame. Alle acceleratie<br />
in een frame worden opgehaald met:<br />
AccelerationEvent[] events = Input.accelerationEvents;<br />
Zo’n event bevat niet enkel de acceleratie in drie dimensies, maar ook de<br />
tijd sinds de laatste meting. Via de gyroscope wordt de snelheid van rotatie in<br />
drie dimensies opgehaald. Hiermee kan ook de oriëntatie opgevraagd worden<br />
wat een quaternion teruggeeft. Een quaternion is een manier om rotatie voor<br />
te stellen, gebaseerd op complexe getallen. Het bestaat uit vier componenten,<br />
die best niet direct worden aangesproken of aangepast. Meestal haalt men<br />
hieruit de Euler-hoeken.<br />
Quaternion quatrotatie = Input.gyro.attitude;<br />
Vector3 eulerrotatie = quatrotatie.eulerangles;<br />
quatrotatie = Quaternion.Euler(0,30,0);<br />
Dit geeft de hoeken om de x-,y- en z-as in graden of maakt een quaternion<br />
van de drie opgegeven hoeken.
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 17<br />
3.3.1 Positiebepaling<br />
Om de positie van de smartphone te bepalen wordt voornamelijk gebruik<br />
gemaakt van de accelerometer. Dit proces gebeurt in drie stappen. Als eerste<br />
wordt de afwijking en ruis nagegaan. Hiervoor wordt de smartphone plat op<br />
tafel gelegd zodat enkel de invloed van de zwaartekracht gemeten wordt.<br />
In een tweede stap wordt een eenvoudige beweging in één richting getest.<br />
De acceleratie van zwaartekracht en die van beweging moeten van elkaar gescheiden<br />
worden. De interface van de gyroscope biedt deze twee acceleraties<br />
al aan. Deze worden bepaald door gebruik te maken van de gyroscope en<br />
accelerometer tesamen. Met de gyroscope kan de orintatie van de smartphone<br />
bepaald worden. Hierdoor is de hoek waaronder de zwaartekracht invloed<br />
heeft gekend, waarmee beide acceleraties van elkaar gesplitst kunnen worden.<br />
Tot slot kan uit de acceleratie de positie bepaald worden als de startpositie<br />
gekend is. Per update in Unity worden alle acceleratie-events opgevraagd.<br />
Met de midpunt-methode [1] wordt de snelheid berekend, aangezien de vorige<br />
acceleratie en de tijd sinds de vorige gekend is. Hierna de snelheid nogmaals<br />
integreren bepaalt de positie. In de volgende paragraaf worden de resultaten<br />
van de positiebepaling besproken. Daarna volgen de resultaten van de<br />
oriëntatiebepaling.<br />
3.3.2 Positiebepaling van een eenvoudige beweging<br />
Om de nauwkeurigheid van de accelerometer te testen, zijn eerst acceleraties<br />
gemeten in rust. Dit geeft enkel de invloed van de zwaartekracht. De verwachte<br />
waarden zijn (0g,0g,-1g). Onderstaande grafiek toont het verschil met<br />
de verwachte waarden.<br />
Figuur 3.5: Afwijking en ruis op acceleraties<br />
Er is te zien dat de y- en z-acceleraties niet helemaal correct zijn. Dit is<br />
opgelost door een korte calibratie in te voeren bij de start van de applicatie.<br />
Er worden voor een paar seconden acceleraties gemeten, waarbij verondersteld<br />
wordt dat de smartphone plat op tafel ligt. Het gemiddelde van deze<br />
acceleraties wordt vervolgens afgetrokken van de volgende meetwaarden. Op<br />
de figuur is ook de invloed van ruis goed te zien. Dit is een meting met één<br />
device, de afwijking is verschillend per device.
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 18<br />
Vervolgens is de bewegingsacceleratie getest. Hiervoor is enkel links en<br />
rechts bewogen zonder te draaien. Dit beperkt de acceleraties tot de x-as. Op<br />
deze manier zijn meerdere verschillende bewegingen uitgevoerd. Hieronder<br />
worden de metingen besproken van een beweging, waar 40 centimeter naar<br />
links wordt bewogen, vervolgens wordt zonder stop terug naar de startpositie<br />
bewogen. Na een korte stop wordt deze beweging nogmaals uitgevoerd. De<br />
acceleraties langs de x-as zijn te zien in Figuur ?? in m/s.<br />
Figuur 3.6: X-acceleraties zonder aanpassing<br />
Hierop is duidelijk te zien dat er bewogen is, maar er zijn teveel acceleratiemomenten.<br />
Om de discrete acceleraties een beetje af te vlakken is het<br />
lopend gemiddelde genomen over tien metingen (Figuur 3.7). Dit aantal is<br />
gekozen aangezien er ongeveer honderd metingen per seconde plaatsvinden.<br />
Figuur 3.7: Het lopend gemiddelde van de X-acceleraties<br />
Een eerste integratie bepaalt de snelhied (Figuur 3.8). De volgende integratie<br />
geeft de positie (Figuur 3.9).<br />
Figuur 3.8: De snelheid langs de X-as met ruis
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 19<br />
Figuur 3.9: De verplaatsing langs de X-as met ruis<br />
De eerste vaststelling is dat de snelheid blijft dalen. In de grafiek van<br />
verplaatsing is niet de juiste beweging te zien. Om het resultaat te verbeteren,<br />
is geprobeerd om de ruis weg te nemen.<br />
Deze ruis is weggewerkt met een high-pass-filter. Enkel als de acceleratie<br />
groot genoeg is, wordt de waarde behouden anders is de acceleratie nul. De<br />
grenswaarden worden bekomen tijdens de meting in rust, door het maximum<br />
en minimum te nemen. Het lopend gemiddelde ziet er nu als volgt uit.<br />
Figuur 3.10: Het lopend gemiddelde van de X-acceleraties zonder ruis<br />
Dit geeft terug na dubbele integratie volgende snelheid en verplaatsing.<br />
Figuur 3.11: De snelheid langs de X-as zonder ruis<br />
Figuur 3.12: De verplaatsing langs de X-as zonder ruis
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 20<br />
Hier is een tweede probleem te zien. Zodra er bewogen is, komt er een fout<br />
op de snelheid. De snelheid wordt nooit exact terug nul en deze afwijking<br />
verandert telkens er bewogen wordt. Dit kan verbeterd worden als er verondersteld<br />
wordt dat de smartphone stilligt wanneer er genoeg opeenvolgende<br />
acceleraties zijn met als waarde nul. Nu wordt volgend resultaat bekomen.<br />
Figuur 3.13: De snelheid langs de X-as<br />
Figuur 3.14: De verplaatsing langs de X-as<br />
Nog steeds is de uitgevoerde beweging niet duidelijk te zien, behalve de<br />
eerste. Andere metingen voor dezelfde beweging resulteerden telkens in helemaal<br />
andere uitkomsten. Tot slot nog opmerken dat de verplaatsing die<br />
gemeten wordt een grootteorde heeft van enkele centimeters, terwijl de werkelijke<br />
beweging tot veertig centimeter verplaatste.<br />
3.3.3 Oriëntatiebepaling<br />
Positiebepaling werd enkel onderzocht met een beweging in één dimensie.<br />
Wanneer beweging in drie dimensies zou toegelaten worden blijft de fout op<br />
de werkelijke positiebepaling alsmaar meer groeien. Als hier nog eens vrije<br />
rotatie aan toegevoegd wordt, verandert de invloed van zwaartekracht langs<br />
de assen. De zwaartekrachtacceleratie moet dus gescheiden worden van de bewegingsacceleratie.<br />
Hiervoor wordt de oriëntatie van de smartphone gebruikt,<br />
die met de gyroscope te achterhalen is. De resultaten van één van de tests<br />
worden besproken.<br />
De smartphone wordt plat op tafel gelegd voor een aantal seconden. Vervolgens<br />
worden er draaibewegingen van 180 ◦ uitgevoerd rond de draaiassen.<br />
Na elke draaibeweging wordt eerst terug naar de startpositie gedraaid voor de<br />
volgende draaibeweging wordt uitgevoerd. Eerst wordt in tegenwijzerzin rond
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 21<br />
de y-as gedraaid, vervolgens in wijzerzin rond de z-as, daarna in wijzerzin<br />
rond de x-as en als laatste in wijzerzin rond de y-as. Op het einde wordt nog<br />
een willekeurige draaibeweging uitgevoerd, waarna de smartphone terug in de<br />
startpositie wordt gelegd (zie Figuur 3.15 en Figuur 3.16).<br />
Figuur 3.15: De rotatie als quaternion<br />
Figuur 3.16: De rotatie in eulerhoeken<br />
Hier is te zien dat wanneer de device stilligt, het resultaat weinig ruis<br />
bevat. De uitgevoerde bewegingen zijn zeer duidelijk waarneembaar. Er is te<br />
zien dat bij het quaternion ook lichte veranderingen te zien zijn wanneer om<br />
één as gedraaid wordt. Dit komt omdat wanneer gedraaid wordt om een as,<br />
het device niet perfect stabiel gehouden wordt in de hand. Er worden dus zeer<br />
kleine rotaties waargenomen. Op het einde is te zien dat de waardes terug<br />
stabilizeren naar de startwaardes.<br />
3.4 Conclusies<br />
Met de gyroscope laat toe dat de oriëntatie van een object nauwkeurig te<br />
bepalen. De accelerometer gebruiken om de positie te bepalen is echter niet<br />
accuraat. Dit komt voornamelijk door ruis en fouten bij het wegnemen van<br />
de zwaartekrachtacceleratie.
HOOFDSTUK 3. ACCELEROMETER EN GYROSCOPE 22<br />
Er bestaan enkele manieren om het resultaat te verbeteren. Op een grote<br />
schaal kan gebruik gemaakt worden van andere sensoren, zoals de GPS. Dit<br />
zorgt dat de afwijking altijd binnen een bepaalde foutmarge blijft dankzij de<br />
GPS. Als de vorm van beweging gekend is, kan het probleem vereenvoudigd<br />
worden. De beweging van een voet bij het wandelen heeft ongeveer een vaste<br />
vorm en patroon. De momenten dat de voet stilstaat kunnen met een andere<br />
sensor, zoals een stappenteller, gemeten worden. Hierdoor zijn er altijd zekere<br />
punten waar geweten is dat de snelheid nul is. Er zou ook enkel gekeken<br />
kunnen worden naar de richting van de versnelling om zo telkens een vaste<br />
afstand te bewegen in plaats van de echte afstand te bepalen.<br />
Het onderzoek zocht naar manieren om de volledige vrijheid in beweging te<br />
kunnen volgen. Met de huidige accelerometers en gyroscopen lukt het niet om,<br />
zonder enige beperking op te leggen of extra sensoren te gebruiken, de positie<br />
te volgen van een smartphone. Omwille van deze beperkingen is hiermee geen<br />
prototype gemaakt.
Hoofdstuk 4<br />
Multiplayer racegame<br />
In dit hoofdstuk worden een aantal technologieën besproken, die bijdragen tot<br />
een prototype van een racegame. Het voornaamste vernieuwende aspect dat<br />
hier bereikt wordt is het dynamisch aanmaken van nieuwe racetracks en deze<br />
delen met andere spelers in een multiplayer. Het hoofdstuk wordt opgedeeld<br />
in drie delen, één per technologie. Het eerste deel zal de Road/Path Tool<br />
behandelen. Hierin wordt besproken hoe de tool werkt en welke aanpassingen<br />
zijn gemaakt om de tool dynamisch te gebruiken voor racetracks. Een volgend<br />
deel gaat over hoe GPS-coördinaten opgehaald worden in Unity en hoe deze<br />
gebruikt worden om een racetrack aan te maken. In het laatste deel wordt<br />
de basiswerking van een photonserver besproken en hoe deze wordt gebruikt<br />
voor een lobbysysteem en multiplayer van het prototype.<br />
4.1 Gebruik van Road/Path Tool<br />
De huidige tool is bedoeld om te gebruiken in de editor. Met enkele aanpassingen<br />
kan het ook dynamisch gebruikt worden. Eerst wordt de normale werking<br />
van de tool besproken. Vervolgens wordt uitgelegd hoe de tool dynamisch<br />
gemaakt wordt.<br />
4.1.1 De tool gebruiken in de editor<br />
In de editor kan de gebruiker nieuwe punten op een terrein aanduiden. De tool<br />
tekent de vorm van de mesh door de aangeduide punten. De punten kunnen<br />
onderling nog verplaatst worden in de editor, maar er is geen mogelijkheid om<br />
tussen twee punten een nieuw punt toe te voegen. Er is de mogelijkheid om<br />
de breedte en smoothing in te stellen. De breedte bepaalt de breedte van de<br />
baan en hoe hoger de smoothing, hoe meer driehoekjes tussen twee punten.<br />
Hogere smoothing zorgt dat de baan beter afgerond wordt in bochten (Figuur<br />
4.1).<br />
23
HOOFDSTUK 4. MULTIPLAYER RACEGAME 24<br />
Figuur 4.1: Een stuk baan met lage en hoge smoothing<br />
Eén van de problemen met de tool wordt zichtbaar wanneer een te scherpe<br />
bocht gemaakt wordt met te hoge smoothing. Er is dan te weinig plaats voor<br />
de grote hoeveelheid driehoekjes, wat resulteert in een mesh die overlapt in<br />
die bochten (Figuur 4.2). Hiermee moet rekening gehouden worden bij het<br />
dynamisch aanmaken van de track.<br />
Figuur 4.2: Een overlappende mesh en de resulterende track<br />
De tool werkt ook niet heel goed op niet vlak terrein. Wanneer het terrein<br />
niet effen is onder de baan, is er kans dat delen van het terrein boven de baan<br />
zichtbaar zijn (Figuur 4.3).
HOOFDSTUK 4. MULTIPLAYER RACEGAME 25<br />
Figuur 4.3: Delen van het terrein komen door de racetrack<br />
4.1.2 Dynamisch gebruik<br />
Om de tool dynamisch te gebruiken moet niet veel aangepast worden aan de<br />
normale werking van het script. De tool verwacht coördinaten op het terrein<br />
in volgorde. Om de opgenomen coördinaten door te geven aan de tool is een<br />
instantie van het script nodig.<br />
AttachedPathScript script = (AttachedPathScript)gameObject.<br />
GetComponent("AttachedPathScript");<br />
script.SendMessage ("CreatePathNode", new Vector3 (x, y, z));<br />
GameObject is het object waaraan het huidige script is verbonden. Hieraan<br />
hangt ook het script van de tool, AttachedPathScript. Met de methode<br />
SendMessage kunnen functies van het andere script opgeroepen worden. De<br />
eerste parameter is de naam van de methode, die opgeroepen moet worden.<br />
Als tweede parameter wordt een eventueel argument meegegeven voor de methode.<br />
Hier wordt een punt meegegeven voor de racetrack. Pas wanneer alle<br />
punten toegevoegd zijn, kan de mesh van de racetrack echt afgewerkt worden.<br />
script.SendMessage ("FinalizePath");<br />
In de volgende paragraaf wordt besproken welke coördinaten worden gebruikt<br />
voor de track en hoe deze verwerkt worden.<br />
4.2 Behandeling van GPS-coördinaten voor racetrack<br />
Om nu dynamisch een racetrack aan te maken is er nood aan punten. Er is<br />
gekozen om GPS-coördinaten te gebruiken. Deze kunnen opgenomen worden<br />
met een smartphone. Hierdoor kan de gebruiker een weg afleggen in een auto<br />
en vervolgens een racetrack genereren met de opgenomen GPS-coördinaten.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 26<br />
4.2.1 GPS gebruiken in Unity<br />
Om gebruik te maken van een GPS van een smartphone, moet deze eerst<br />
opgestart worden. Dit kan gebeuren met volgende code.<br />
if (Input.location.isEnabledByUser) {<br />
Input.location.Start();<br />
int wait = 20;<br />
while (Input.location.status<br />
== LocationServiceStatus.Initializing && wait>0) {<br />
yield return new WaitForSeconds(1);<br />
wait--;<br />
}<br />
if (Input.location.status == LocationServiceStatus.Failed) {<br />
return;<br />
}<br />
else {<br />
gpsInit = true;<br />
InvokeRepeating ("RetrieveGPSData", 0, 2);<br />
}<br />
}<br />
else {<br />
Debug.Log("GPS not available");<br />
}<br />
Er wordt eerst nagegaan of de GPS-service wel mogelijk is met isEnabled-<br />
ByUser. Vervolgens wordt de GPS opgestart met de Start-functie. Deze kan<br />
twee parameters meekrijgen. De eerste bepaalt de gewenste nauwkeurigheid in<br />
meter, de tweede stelt in na hoeveel meter de GPS update. Beide parameters<br />
staan standaard ingesteld op tien meter en werden niet gewijzigd.<br />
Aangezien het starten van de service soms enige tijd duurt, is het noodzakelijk<br />
om enkele seconden te wachten terwijl de status nog op initialisatie<br />
staat. De status wordt opgehaald met LocationServiceStatus. De verschillende<br />
statussen zijn: stopped, initializing, running en failed.<br />
Als de service goed is opgestart kan je instellen welke functie herhaaldelijk<br />
opgeroepen wordt om de data op te halen. Dit gebeurt met InvokeRepeating.<br />
De eerste parameter is de functienaam, de tweede parameter is het aantal<br />
seconden dat nog gewacht wordt voor de functie wordt opgeroepen en de laatste<br />
parameter bepaalt om de hoeveel seconden de functie wordt opgeroepen.<br />
In het voorbeeld wordt de functie RetrieveGPSData om de twee seconden<br />
opgeroepen dit start onmiddellijk.<br />
In de methode RetrieveGPSData kan vervolgens de GPS-data opgehaald<br />
worden aan de hand van Input.location.lastData. Hiermee wordt een struct<br />
van het type, LocationInfo, opgehaald. Deze struct biedt onder andere toegang<br />
tot de longitude en latitude van de GPS.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 27<br />
4.2.2 Verwerken GPS-coördinaten<br />
De GPS-coördinaten geprojecteerd worden op een vlak terrein in Unity. Dit<br />
terrein heeft dimensies van 2000 op 2000 units. De longitude en latitude<br />
van de GPS kunnen niet onmiddellijk gebruikt worden voor de racetrack, de<br />
coördinaten moeten eerst omgezet worden in een x- en een z-waarde. De<br />
y-waarde bepaalt de hoogte op het terrein. Deze is voor elk punt van de<br />
racetrack nul. Om te testen of de projectie een correct resultaat gaf en of de<br />
opname met GPS accuraat is, zijn coördinaten opgenomen langs een traject<br />
(Figuur 4.4).<br />
Figuur 4.4: De baan waarlangs coördinaten zijn opgenomen<br />
Om de GPS-coördinaten te converteren is eerst geprobeerd om de latitude<br />
en longitude om te zetten met een translatie en schaling.<br />
posz = (latitude + translatiez)*schaal + 1000;<br />
posx = (longitude + translatiex)*schaal + 1000;<br />
Het eerste punt van de racetrack wordt in het midden van het terrein<br />
gelegd. Hiervoor worden translatiez en translatiex respectievelijk gelijk gesteld<br />
met het tegengestelde van de eerste latitude en longitude. Vervolgens wordt<br />
na deze translatie geschaald, de startwaarde van deze schaling is experimenteel<br />
ingesteld. Vervolgens wordt nog een translatie uitgevoerd met de helft van de<br />
breedte en de hoogte van het terrein. Hiermee wordt het eerste punt in het<br />
midden van het terrein geplaatst. Wanneer nieuwe punten van de racetrack<br />
buiten het terrein zouden liggen, wordt de schaling telkens met een factor<br />
verkleind. Dit vereist ook dat alle voorgaande punten ook geschaald worden.<br />
Het is ook mogelijk om telkens het terrein te vergroten, maar dit zorgt voor een<br />
groot performantieverlies tijdens het spel. Het resultaat van deze omzetting<br />
is te zien in Figuur 4.5.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 28<br />
Figuur 4.5: Simpele omzetting van GPS-coördinaten naar terreincoördinaten<br />
De berekende baan komt niet exact overeen met de echte baan, maar de<br />
eigenlijke vorm van het traject is wel goed terug te vinden. Het grootste<br />
probleem is de breedte.<br />
Om de omzetting te verbeteren is gebruik gemaakt van de Universele<br />
Transversale Mercatorprojectie(UTM).<br />
”De Mercator projectie is een cilinderprojectie: een punt op de bol wordtgeprojecteerd<br />
op een cilindervlak, dat de bol omhult. De raakcirkel tussencilinder<br />
en bol is in dit geval de evenaar. Door het cilindervlak als het wareuit te rollen<br />
wordt een plat kaartvlak verkregen. Bij de transversale Merca-tor-projectie<br />
wordt de cilinder 90 ◦ gekanteld, zodat de cilinder aan de bolraakt in een meridiaan,<br />
de zogenaamde centrale meridiaan.”(Crombaghs & Kösters, 2000)[2]<br />
Voor het resultaat van deze projectie, zie Figuur 4.6.<br />
Figuur 4.6: Omzetting met Mercatorprojectie<br />
Nu is te zien dat de track bijna perfect overeenkomt met de afgelegde weg.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 29<br />
Om echter dit resultaat te verkrijgen zijn de coördinaten op een aantal andere<br />
manieren verwerkt.<br />
Aangezien tijdens de opname een groot aantal opeenvolgende duplicaten<br />
opgenomen worden, moeten deze eerst verwijderd worden. Een volgende nodige<br />
aanpassing aan de coördinaten is om een gemiddelde van een aantal<br />
punten te nemen om de uiteindelijke track beter af te ronden (Figuur 4.7).<br />
Figuur 4.7: Een deel van de racetrack zonder en met het gemiddelde van een<br />
aantal opeenvolgende punten<br />
Een laatste aanpassing is zorgen dat opeenvolgende punten niet te dicht bij<br />
elkaar liggen of dat de hoek tussen drie opeenvolgende punten niet te scherp<br />
is. Dit laatste is om het overlappingsprobleem van de Road/Path Tool te<br />
verhinderen. De hoek tussen drie punten kan makkelijk berekend worden aan<br />
de hand van het vectorproduct. Als de hoek scherp is, wordt het punt in het<br />
midden verwijderd.<br />
4.3 Werking photonserver<br />
Om multiplayer functionaliteit toe te voegen aan het prototype was nood aan<br />
een server waarmee makkelijk een lobbysysteem en de multiplayer zelf kon<br />
gemaakt. Een photonserver biedt deze functionaliteit aan en laat toe om dit<br />
snel te integreren in een eigen project. De voornaamste functionaliteit, die<br />
een photonserver biedt, is het versturen van events. Het is mogelijk om eigen<br />
events te declareren en klaar te zetten om door de server te laten versturen.<br />
Het is ook noodzakelijk om de nodige methoden te voorzien waarmee
HOOFDSTUK 4. MULTIPLAYER RACEGAME 30<br />
de nieuwe events worden opgevangen. De multiplayer bestaat uit drie grote<br />
delen, de spelers, de lobby en de kamers, waar de multiplayer zich afspeelt.<br />
4.3.1 De spelers<br />
De spelers worden voorgesteld in een Player-klasse. De Player-klasse bevat<br />
de informatie van de spelers, die nodig is om ze lokaal voor te stellen. In het<br />
geval van de racegame bevat deze klasse onder andere de naam, de positie<br />
en rotatie van de speler. Ook de nodige data om de racetrack aan te maken<br />
wordt bij de spelers opgeslaan. De host verstuurt deze data naar alle andere<br />
spelers, die in hetzelfde spel komen.<br />
4.3.2 Lobby<br />
De beschikbare kamers worden gebundeld in de lobby. Spelers kunnen in de<br />
lobby gaan en zien daar alle kamers waar andere spelers hun racetrack hosten.<br />
Om in een kamer te komen doorloopt de speler een aantal stappen. Als eerste<br />
wordt er geconnecteerd met de photonserver.<br />
internal override void Connect()<br />
{<br />
if (this.Peer == null)<br />
{<br />
this.Peer = new LiteLobbyPeer(this, this.UsedProtocol);<br />
}<br />
this.Players = new Dictionary();<br />
this.LocalPlayer = new Player(0);<br />
if(Track.NUMBER != -1)<br />
{<br />
LocalPlayer.track = Game.tracks[Track.NUMBER];<br />
LocalPlayer.width = Track.WIDTH;<br />
LocalPlayer.smooth = Track.SMOOTH;<br />
}<br />
this.DebugReturn("Trying to connect...");<br />
this.Peer.Connect(this.ServerAddress, this.ServerApplication);<br />
}<br />
In bovenstaande code wordt een nieuwe Peer aangemaakt. Hiermee kan geconnecteerd<br />
worden met de server en dit zorgt ook dat events worden doorgestuurd,<br />
hierover wordt later meer uitgelegd. Vervolgens wordt een lijst aangemaakt<br />
van Player-objecten. Wanneer een speler in een kamer gaat, worden<br />
hier lokale versies van alle andere spelers in die kamer bewaard. Er wordt<br />
ook een Player-object aangemaakt voor de huidige speler. Het is mogelijk<br />
om hier nog andere initialisaties uit te voeren. Hier wordt de data van de<br />
racetrack ingevuld voor de lokale speler, wanneer het tracknummer niet -1 is.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 31<br />
Dit betekent dat de speler een host is en dus zijn track deelt met de andere<br />
spelers. Wanneer de speler zich in een kamer bevindt, wordt de informatie<br />
van de track naar andere spelers in dezelfde kamer gestuurd aan de hand van<br />
een zelfgedefiniëerde event.<br />
Nadat geconnecteerd is met de server en voor de speler in een kamer gaat,<br />
komt de speler in de lobby, waar alle kamers zichtbaar zijn. Hier wordt<br />
lokaal een verzameling van alle kamers aangemaakt, deze wordt regelmatig<br />
geüpdated door de server.<br />
public void JoinLobby(string lobbyName)<br />
{<br />
this.LobbyName = lobbyName;<br />
this.ChatState = ChatStateOption.JoiningLobbyRoom;<br />
this.RoomHashtable = new Hashtable();<br />
this.Peer.OpJoin(lobbyName);<br />
}<br />
De host kan nu een nieuwe kamer maken. De andere gebruikers kunnen in<br />
reeds aangemaakte kamers gaan.<br />
4.3.3 Multiplayer<br />
Wanneer in een kamer gegaan wordt, moet OpJoinFromLobby van de Peer<br />
opgeroepen worden. Hieraan worden de naam van de kamer, de lobbynaam<br />
en eventuele eigenschappen meegegeven. De laatste parameter bepaalt of deze<br />
eigenschappen ook naar alle andere spelers worden gestuurd. Indien de kamer<br />
nog niet bestaat, wordt deze aangemaakt door de server.<br />
public void JoinRoomFromLobby(string roomName)<br />
{<br />
this.RoomName = roomName;<br />
Hashtable properties = new Hashtable() {};<br />
this.Peer.OpJoinFromLobby(this.RoomName,<br />
this.LobbyName, properties, true);<br />
}<br />
De server kent een unieke nummer toe aan een speler, die in een kamer gaat.<br />
Er wordt ook een Join-event verstuurd, alle spelers ontvangen deze event,<br />
ook de speler, die net in de kamer ging. Deze event bevat onder andere het<br />
aantal spelers in de kamer. Als lokaal het aantal spelers niet overeenkomt,<br />
wordt de lijst aangepast door lokaal nieuwe Player-objecten aan te maken of<br />
objecten uit de lijst te verwijderen. De host verstuurt ook de nodige data om<br />
de racetrack aan te maken naar de nieuwe spelers. In de racegame worden<br />
ook nieuwe instanties aangemaakt van racewagen-objecten voor elke speler in<br />
de kamer.
HOOFDSTUK 4. MULTIPLAYER RACEGAME 32<br />
public override void OnEvent(EventData photonEvent)<br />
{<br />
base.OnEvent(photonEvent);<br />
//Hier wordt de data uit de event gehaald<br />
Hashtable evData = photonEvent[(byte)LiteEventKey.Data] as Hashtable;<br />
int originatingActorNr = 0;<br />
if (photonEvent.Parameters.ContainsKey((byte)LiteEventKey.ActorNr))<br />
{<br />
originatingActorNr = (int)photonEvent[(byte)LiteEventKey.ActorNr];<br />
}<br />
Player originatingPlayer;<br />
//Hier wordt adhv de unieke nummer de bron van de event opgehaald<br />
//uit de lokale lijst van spelers<br />
this.Players.TryGetValue(originatingActorNr, out originatingPlayer);<br />
}<br />
//Nu wordt nagegaan welke soort event het is<br />
switch (photonEvent.Code)<br />
{<br />
//Een van de eigengedefinieerde events waar de<br />
//posite mee wordt verstuurd<br />
case (byte)Player.DemoEventCode.PlayerMove:<br />
if (originatingPlayer != null &&<br />
!originatingPlayer.Equals(LocalPlayer))<br />
{<br />
originatingPlayer.SetPosition(evData);<br />
}<br />
}<br />
Alle spelers zetten telkens na een instelbaar tijdsinterval events klaar, die<br />
vervolgens via de server naar andere spelers worden doorgestuurd. De andere<br />
spelers ontvangen deze events in een overschreven OnEvent-methode. Bovenstaande<br />
code toont hoe deze verwerkt worden. De events bevatten het<br />
id van de speler, die de event heeft verstuurd. Dit laat toe om lokaal het<br />
juiste Player-object aan te passen. De events krijgen ook een eventcode mee.<br />
Hiermee worden alle events in kleinere pakketjes opgedeeld, zo zijn er bijvoorbeeld<br />
events waarmee enkel de positie van een speler wordt verstuurd<br />
en andere waarmee de rotatie van een speler wordt verstuurd. De data in<br />
events wordt bijgehouden in een hashtabel. Het verpakken en uitpakken van<br />
data wordt uitgevoerd in de Player-klasse, aangezien hier de lokale data wordt<br />
bijgehouden.<br />
//Een methode in de Player-klasse<br />
//SetPosition zal lokaal de positie updaten adhv eventdata<br />
internal void SetPosition(Hashtable evData)
HOOFDSTUK 4. MULTIPLAYER RACEGAME 33<br />
{<br />
}<br />
//De index van de data kan zelf gedefinieerd worden<br />
this.posX = (float)evData[(byte)DemoEventKey.PlayerPositionX];<br />
this.posY = (float)evData[(byte)DemoEventKey.PlayerPositionY];<br />
In de racegame sturen spelers hun positie en rotatie naar alle anderen.<br />
Deze passen de positie en rotatie van de lokale versies van de spelers aan, waardoor<br />
ook de racewagen-objecten zullen bewegen. Bovenstaande code haalt de<br />
data uit de ontvangen event en past de positie van het Player-object aan. Onderstaande<br />
methode verpakt de positie van de lokale speler in een hashtabel<br />
en roept de peer aan om een event met die data klaar te zetten om verstuurd<br />
te worden.<br />
//Een functie in de Player-klasse<br />
//Deze functie zal de positiedata verpakken<br />
//en klaarzetten om verstuurd te worden<br />
internal void SendEvMove(LitePeer peer)<br />
{<br />
if (peer == null)<br />
{<br />
return;<br />
}<br />
//Data verpakken<br />
Hashtable eventContent = new Hashtable();<br />
eventContent.Add((byte)DemoEventKey.PlayerPositionX,<br />
(float)this.posX);<br />
eventContent.Add((byte)DemoEventKey.PlayerPositionY,<br />
(float)this.posY);<br />
//Hier wordt data nog niet onmiddellijk verzonden,<br />
//maar in een wachtlijst gezet<br />
peer.OpRaiseEvent((byte)DemoEventCode.PlayerMove,<br />
eventContent, isSendReliable, (byte)0);<br />
}<br />
Om alle events in de wachtlijst te versturen, moet volgende methode opgeroepen<br />
worden, this.Peer.SendOutgoingCommands<br />
4.4 Extra functionaliteit voor het prototype<br />
Voor het prototype was nog een racewagen-object nodig. Hiervoor is de racewagen<br />
van een Unity-tutorial gebruikt. Een andere toevoeging zijn checkpoints.<br />
Deze objecten worden geplaatst op de punten van de track (Figuur<br />
4.8). De checkpoints werken als trigger. Dit wil zeggen dat wanneer een ander
HOOFDSTUK 4. MULTIPLAYER RACEGAME 34<br />
object erdoor gaat, wordt een event afgevuurd. In deze event kan nagegaan<br />
worden welk object door de checkpoint is gegaan, in het geval van de racegame<br />
zijn dit de racewagens. De spelers moeten door alle checkpoints gaan om de<br />
race te vervolledigen. Dit wordt ook nog gebruikt om de positie te bepalen<br />
in de race. De speler, die al door het meeste checkpoints gegaan is, staat<br />
eerst. Als het aantal gelijk is, wordt gekeken naar de afstand tot het volgend<br />
checkpoint.<br />
Figuur 4.8: De checkpoints op de racetrack<br />
4.5 Conclusies<br />
De tool om racetracks aan te maken werkt zeer goed dynamisch. De enige<br />
beperkingen zijn dat het niet optimaal werkt op niet vlak terrein en bij te<br />
scherpe bochten overlapt de mesh. De aanpassingen om de tool dynamisch te<br />
gebruiken waren minimaal.<br />
De opgenomen GPS-coördinaten zijn zeer accuraat met het in werkelijkheid<br />
gevolgde pad. Een gewone projectie leidt tot een vervormde track. Het<br />
gebruik van UTM om de coördinaten om te vormen tot punten op het terrein<br />
geeft een zeer goed resultaat.<br />
Het gebruik van photonserver laat toe om snel een lobbysysteem aan te<br />
maken. Het is ook zeer geschikt om multiplayer-funcionaliteit toe te voegen.<br />
Er kunnen berichten worden samengesteld, die de server vervolgens naar alle<br />
spelers kan sturen. Alle andere spelers kunnen makkelijk te weten komen van<br />
welke speler dit bericht afkomstig is. Lokaal kunnen de berichten uitgepakt<br />
worden en kunnen de nodige acties ondernomen worden.
Hoofdstuk 5<br />
Brain Computer Interface<br />
”Een brain-computer interface of BCI is een technologie waarbij bepaalde hersensignalen<br />
worden gemeten en gedigitaliseerd die vervolgens door een computer<br />
worden geclassificeerd en in acties worden omgezet. Zo is het bijvoorbeeld<br />
al mogelijk gebleken om afgaande van hersenactiviteit een pijl op het computerscherm<br />
naar links of rechts te laten wijzen.”(http://nl.wikipedia.org/<br />
wiki/Brain-computer_interface)[3]<br />
5.1 Werking Mindwave Mobile<br />
De mindwave mobile is een sensor van Neurosky, waarmee hersengolven gemeten<br />
worden. In tegenstelling tot vorige producten van Neurosky, maakt<br />
de mindwave mobile gebruik van bluetooth om data te versturen. Dit laat<br />
toe dat de device kan gekoppeld worden met smartphones, maar ook met pc.<br />
Er is getest hoe de mindwave connecteert met een android, hoe data wordt<br />
opgehaald en of deze gebruikt kon worden in een prototype.<br />
5.1.1 Connecteren met Mindwave Mobile<br />
Om te connecteren met de mindwave moet eerst de correcte seriële poort<br />
gevonden worden, waarmee de smartphone en de mindwave gelinkt zijn. Deze<br />
connectie met de seriële poorten is niet rechtstreeks, er bevindt zich nog een<br />
extra laag tussen, genaamd thinkgear. Het voornaamste dat dit doet is de<br />
seriële data omzetten in de data, die vervolgens gebruikt wordt in applicaties.<br />
Wanneer de gebruiker probeert te connecteren, worden de seriële poorten<br />
afgelopen tot een verbinding tot stand is gekomen. De mindwave stuurt nu<br />
data door naar de thinkgear-laag. Deze verwerkt alle data en stuurt berichten<br />
door naar hogere lagen. Die berichten worden opgevangen, het soort data<br />
wordt nagegaan en de data wordt opgeslaan.<br />
Er worden een aantal verschillende thinkgear-bibliotheken aangeboden,<br />
afhankelijk van het platform waarvoor geprogrammeerd wordt. Aangezien er<br />
met android wordt gewerkt, is er gebruik gemaakt van de Java-bibliotheek.<br />
35
HOOFDSTUK 5. BRAIN COMPUTER INTERFACE 36<br />
Het connecteren met de device en een handler aanmaken om binnenkomende<br />
data op te vangen is het makkelijkst te programmeren in Java-code. De data<br />
moet echter op een manier in Unity beschikbaar zijn. Aangezien Java niet<br />
rechtstreeks in Unity gebruikt kan worden, is een plugin gemaakt. Om dit te<br />
verwezenlijken, leidt de Java-klasse af van UnityPlayerActivity. De Java-code<br />
wordt samen met de thinkgear-bibliotheek in een nieuwe jar verpakt.<br />
//thinkgear-bibliotheek includeren<br />
import com.neurosky.thinkgear.*;<br />
import com.unity3d.player.UnityPlayerActivity;<br />
public class ThinkgearActivity extends UnityPlayerActivity {<br />
@Override<br />
public void onCreate(Bundle savedInstanceState) {<br />
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();<br />
//De koppeling met de thinkgear-laag<br />
tgDevice = new TGDevice(bluetoothAdapter, handler);<br />
}<br />
public static void connect() {<br />
if(tgDevice.getState() != TGDevice.STATE_CONNECTING<br />
&& tgDevice.getState() != TGDevice.STATE_CONNECTED){<br />
tgDevice.connect(rawEnabled);<br />
}<br />
}<br />
}<br />
private static Handler handler = new Handler() {<br />
@Override<br />
public void handleMessage(Message msg) {<br />
switch (msg.what) {<br />
case TGDevice.MSG_ATTENTION:<br />
attention = msg.arg1;<br />
break;<br />
...<br />
}<br />
}<br />
}<br />
5.2 Integratie in Unity<br />
De jar kan gebruikt worden in Unity als plugin. Nu moet in Unity enkel<br />
een instantie van ThinkgearActivity aangemaakt worden. De handler in Java
HOOFDSTUK 5. BRAIN COMPUTER INTERFACE 37<br />
zorgt dat een aantal statische variabelen geüdated worden. In Unity worden<br />
deze variabelen opgevraagd en gebruikt in een prototype.<br />
thinkgearplugin =<br />
new AndroidJavaClass("com.test.helloeeg.ThinkgearActivity");<br />
//statische methode oproepen<br />
thinkgearplugin.CallStatic("connect");<br />
//statische variabele opvragen<br />
float attention = thinkgearplugin.GetStatic("attention");<br />
Merk op dat er geen echt object van de ThinkgearActivity wordt aangemaakt.<br />
Het werkt als een soort klasse met statische variabelen en methoden.<br />
De handler vangt achter de schermen berichten op en zorgt ervoor dat de<br />
statische variabelen worden aangepast.<br />
5.3 Prototype<br />
Er worden drie waarden gemeten met de mindwave mobile. Het meet de focus<br />
van de gebruiker, hoe rustig de gebruiker is en of de gebruiker knippert. Deze<br />
waarden zijn gebruikt in een prototype. Het prototype maakt voornamelijk<br />
gebruik van de focus van de gebruiker. Met een hoge focus is er vooruitgang.<br />
Bij lage focus of wanneer de gebruiker knippert, gaat de tegenstander vooruit.<br />
Het doel is om als eerste tot het einde te raken. De toestand van de connectie<br />
en de gemeten waarden worden ook weergegeven.<br />
5.3.1 Conclusies<br />
De gemeten waarden van de mindwave mobile zijn nogal abstract en het is<br />
niet makkelijk om na te gaan of ze helemaal correct zijn. Na het device enkele<br />
keren te gebruiken, worden de waarden wel meer beïnvloedbaar. Als men zich<br />
bijvoorbeeld op één ding focust dan geeft de mindwave hiervoor ook een hoge<br />
waarde. Aangezien de gebruiker bewust de waarden kan beheersen, kunnen<br />
ze gebruikt worden als input voor een prototype.
Besluit<br />
De meeste, onderzochte technologieën bleken geschikt om een nieuw soort<br />
gameplay aan te bieden.<br />
Om gebruik te maken van Flash-animaties in Unity, is uniSWF meer geschikt<br />
dan Iggy. UniSWF maakt het mogelijk om animaties als objecten te<br />
gebruiken in Unity en laat ook toe dat animaties enkel over het camerabeeld<br />
worden afgespeeld. De zeer makkelijke interface is zeer geschikt om de animaties<br />
te beheersen. Dit biedt niet veel nieuwe gameplay aan, maar laat wel<br />
complexe animaties toe voor objecten in Unity en het is zeer handig om meer<br />
ingewikkelde user-interfaces te maken.<br />
De accelerometer van een smartphone was niet bruikbaar om de beweging<br />
van de device te volgen. Dit was ten gevolge van ruis en een accumulerende<br />
fout op de positiebepaling. De oriëntatie van de device kon wel nauwkeurig<br />
bepaald worden aan de hand van de gyroscope. Om het resultaat van<br />
de accelerometer te verbeteren kan mogelijks gebruik gemaakt worden van<br />
een Kalman-filter. Hiermee zou het mogelijk zijn om ruis en de fout op het<br />
resultaat te verminderen.<br />
De Road/Path tool werd gebruikt om racetracks in Unity te maken. Hieraan<br />
zijn enkele aanpassingen gemaakt om de tool dynamisch te laten werken.<br />
Vervolgens is getest of opgenomen GPS-coördinaten gebruikt konden worden<br />
voor de racetrack. Door gebruik te maken van Universele Transversale Mercatorprojectie,<br />
werden de coördinaten correct omgezet naar punten op een<br />
terrein in Unity. De resulterende racetrack kwam zeer goed overeen met het<br />
werkelijke traject. Met een photonserver konden deze tracks gehost worden<br />
in een multiplayer. Hiermee kan makkelijk bepaald worden welke data naar<br />
de andere spelers moet gestuurd worden, zoals de positie en oriëntatie van<br />
een racewagen. De andere spelers kunnen lokale versies van de racewagens<br />
aanpassen aan de hand van de ontvangen data. De vernieuwde gameplay is<br />
hier vooral te vinden in het dynamisch aanmaken van nieuwe racetracks, die<br />
onmiddellijk kunnen worden gebruikt in een multiplayer-game.<br />
Om de Mindwave Mobile van Neurosky te gebruiken om hersengolven te<br />
meten, moest een plugin geschreven worden, zodat de data in Unity kon<br />
gebruikt worden voor een android- applicatie. De gemeten waarden waren<br />
bruikbaar voor een prototype en boden een nieuw soort gameplay. Het aantal<br />
waarden waarmee gewerkt kan worden is nog klein, maar dit komt omdat de<br />
technologie nog maar korte tijd bestaat.<br />
38
Lijst van figuren<br />
1.1 Een bol en kubus in Unity . . . . . . . . . . . . . . . . . . . . 2<br />
1.2 Een eigengemaakt editorvenster . . . . . . . . . . . . . . . . . 5<br />
3.1 Een bekende tilting game . . . . . . . . . . . . . . . . . . . . . 14<br />
3.2 Zwaartekracht op de smartphone . . . . . . . . . . . . . . . . 15<br />
3.3 Een mechanische gyroscope . . . . . . . . . . . . . . . . . . . 15<br />
3.4 De drie draaibewegingen . . . . . . . . . . . . . . . . . . . . . 16<br />
3.5 Afwijking en ruis op acceleraties . . . . . . . . . . . . . . . . . 17<br />
3.6 X-acceleraties zonder aanpassing . . . . . . . . . . . . . . . . . 18<br />
3.7 Het lopend gemiddelde van de X-acceleraties . . . . . . . . . . 18<br />
3.8 De snelheid langs de X-as met ruis . . . . . . . . . . . . . . . 18<br />
3.9 De verplaatsing langs de X-as met ruis . . . . . . . . . . . . . 19<br />
3.10 Het lopend gemiddelde van de X-acceleraties zonder ruis . . . 19<br />
3.11 De snelheid langs de X-as zonder ruis . . . . . . . . . . . . . . 19<br />
3.12 De verplaatsing langs de X-as zonder ruis . . . . . . . . . . . . 19<br />
3.13 De snelheid langs de X-as . . . . . . . . . . . . . . . . . . . . 20<br />
3.14 De verplaatsing langs de X-as . . . . . . . . . . . . . . . . . . 20<br />
3.15 De rotatie als quaternion . . . . . . . . . . . . . . . . . . . . . 21<br />
3.16 De rotatie in eulerhoeken . . . . . . . . . . . . . . . . . . . . . 21<br />
4.1 Een stuk baan met lage en hoge smoothing . . . . . . . . . . . 24<br />
4.2 Een overlappende mesh en de resulterende track . . . . . . . . 24<br />
4.3 Delen van het terrein komen door de racetrack . . . . . . . . . 25<br />
4.4 De baan waarlangs coördinaten zijn opgenomen . . . . . . . . 27<br />
4.5 Simpele omzetting van GPS-coördinaten naar terreincoördinaten 28<br />
4.6 Omzetting met Mercatorprojectie . . . . . . . . . . . . . . . . 28<br />
4.7 Een deel van de racetrack zonder en met het gemiddelde van<br />
een aantal opeenvolgende punten . . . . . . . . . . . . . . . . 29<br />
4.8 De checkpoints op de racetrack . . . . . . . . . . . . . . . . . 34<br />
39
Literatuurlijst<br />
[1] http://en.wikipedia.org/wiki/Midpoint_method<br />
[2] Crombaghs, M. & Ksters, A. (2000). Coördinaattransformaties<br />
en kaartprojecties.<br />
[3] http://nl.wikipedia.org/wiki/Brain-computer_interface<br />
[4] http://www.swfir.com/actionscript.html<br />
[5] http://www.adobe.com/be_nl/products/flash.html<br />
[6] http://unity3d.com<br />
[7] http://docs.unity3d.com/Documentation/Manual/index.<br />
html<br />
[8] http://en.wikipedia.org/wiki/Accelerometer<br />
[9] http://en.wikipedia.org/wiki/Gyroscope<br />
40
Bijlage A<br />
Unity3D Sceneview<br />
1. De scene waarin alle gameobjecten te zien zijn in een 3D-ruimte.<br />
2. De hierarchy. De kubus en bol zijn onder een leeg gameobject gebracht.<br />
Door dit object te verplaatsen worden de kubus en bol ook verplaatst<br />
en ze behouden hun onderlinge positie ten opzichte van elkaar.<br />
3. De projectstructuur waar onder andere scripts en prefabs te vinden zijn.<br />
4. De inspector. Hier zijn de properties van de bol te zien. De transform<br />
eigenschappen bepalen de plaats en oriëntatie ten opzichte van het<br />
gameobject waaronder de bol zit.<br />
41
BIJLAGE A. UNITY3D SCENEVIEW 42
Bijlage B<br />
Unity3D Gameview<br />
1. De Gameview. Dit is wat de speler ziet als het spel start, tenzij de<br />
camera dynamisch verplaatst wordt.<br />
2. Een prefab in de projectstructuur. Het bestaat uit een cilinder en een<br />
kubus en kan dynamisch aangemaakt worden.<br />
3. Een custom Behaviourscript waarmee het object kan gemanipuleerd worden.<br />
4. Een afbeelding van hoe de prefab eruitziet.<br />
43
BIJLAGE B. UNITY3D GAMEVIEW 44