Introductie
Deze tutorial is een introductie gamedevelopment met Unity. Door kleine prototypes te maken doe je kennis op in Basic Gameplay en Sound Effects, hoe deze toe te passen en te gebruiken. Denk daarbij aan objecten vergroten en verkleinen, comfortabel worden met User Input en logische structuren bouwen.
Wat heb je nodig?
- Unity [Unity Store]
- IDE Software [Visual Studio - Notepad++ - SublimeText - Atom - Brackets - Jetbrains Rider]
Uitleg van de layout.
Voordat we aan de slag gaan om games te ontwikkelen, zal het programma gestart moeten worden. Neem de tijd om de interface te bestuderen. Je ziet dat het programma uit meerdere kleine raampjes bestaat. Hieronder staat uitgelegd waar de onderdelen uit bestaan.
Project view
Elk Unity project bestaat uit een Assets map. De onderdelen van deze map worden getoond in de Project View. Dit is waar alle Assets worden opgeslagen van jouw game, zoals scènes, scripts, 3D modellen, textures en geluiden. Je kunt zien waar de assets staan opgeslagen als je met de rechtermuisknop op klikt en drukt op “Reveal in Explorer on Windows”. Belangrijk is, dat je nooit zomaar assets verplaatst via Windows Verkenner, anders zal Unity het niet meer kunnen vinden.
Hierarchy
De Hierarchy bevat elk GameObject in de huidige scène. Sommige objecten kunnen 3Dmodellen zijn, andere objecten zijn wat anders. Hier kun je zien dat sommige objecten een Parent of Child object zijn. Sommige objecten staan verborgen onder een object dat een pijltje ervoor heeft staan. Dit wordt in Unity Parenting genoemd. Dat betekent dat het ene gameobject een onderdeel is van een ander object. Je kunt makkelijk een object, een child maken door het aan te klikken en te slepen over een ander object.
Toolbar
De Toolbar bestaat uit vijf basis bedieningen. Elk bediening heeft een andere relatie naar verschillende onderdelen van het programma.
- Transform gereedschap – wordt gebruikt in de Scène View.
- Transform Gizmo Toggles – invloed op de Scene View weergave.
- Play/Pause/Step Knoppen wordt gebruikt met de Game View.
- Layers Dropdown – aangeven welke objecten worden getoond in Scène View.
- Lay-out Dropdown – aangegeven de plaatsing van alle Views.
- Collab - Tool om backups van je project te maken via de Unity Collab dienst.
Scene view
De Scène View is jouw interactieve zandbak. Je zult de Scène View gebruiken voor het selecteren en plaatsen van omgevingen, de speler, de camera, vijanden en alle andere GameObjects. Het plaatsen en aanpassen van objecten in de Scène View zal de meest belangrijke functies zijn in Unity. Daarom is het belangrijk dat je deze goed leert.
Je houdt de rechtermuisknop ingedrukt zodat je in vliegmodus komt. Dit zorgt ervoor dat de knoppen WASD in je navigatieknoppen verandert. Selecteer elk GameObject en druk op de F-knop. Hierdoor zal het object in het midden van de scene verschijnen. Voor het plaatsen van de GameObject kunnen de andere knoppen gebruikt worden.
- Translate Tool – Het slepen van het object.
- Rotate Tool – Het draaien van het object.
- Scale Tool – Het vergroten of verkleinen van een object.
Er zijn nog veel meer knoppen en functies te vinden, maar daar zullen we later nog een keer op terug komen. Ze zijn nu niet nodig bij het ontwikkelen van de games die we willen maken.
Game View
De Game View is het beeld opgebouwd vanuit de camera in jouw game. Het is het resultaat van jouw spel als het af is.
Gebruik de knoppen in de Toolbar om in Play Mode te gaan, om jouw game uit te proberen. Terwijl je in Play Mode ben, zullen alle veranderingen die je aanbrengt tijdelijk zijn en verdwijnen als je Play Mode uitgaat. Het programma wordt donkerder om je hieraan te herinneren.
Inspector
Games in Unity zijn gemaakt uit verschillende GameObjecten die bestaan uit meshes, geluiden, script of andere elementen zoals licht. De Inspector geeft informatie over het door jouw geselecteerde GameObject, met de daarbij behorende componenten en de eigenschappen.
Game Design
Bij elke game, zelfs elke applicatie, maak je van tevoren documentatie hoe het er uit gaat komen te zien. Dit is handig voor jezelf, zodat je einddoel duidelijk is, maar ook voor eventuele projectgenoten die je gaan helpen of zelfs je baas of klant voor wie je het maakt. Je kan simpelweg zeggen dat bij Game Design twee principes worden behandeld. De intentie en de executie. Oftwel, wat willen wij gaan maken en wat wij uit eindelijk maken. De intentie die wij hebben is als volgt:
Player Experience
Welke ervaring gaat de speler krijgen? Moet de speler het idee krijgen door de oude mijnen in Limburg te zwerven, of te werken op de maan?
Core Mechanic
Welke functionaliteit gaat de game voornamelijk over? Mario gaat over springen over allerlei objecten in de wereld, Space Invaders gaat het voornamelijk over vijandige schepen neerschieten.
Core game loop
Wat gebeurt er continu? Mario draait erom dat de speler blijft doorlopen, springen over objecten, bodemloze punten en vijanden. Space Invaders gaat continu om vijanden neerschieten maar vijandige kogels ontwijken.
Gameflow
Hoe gaat de game verlopen. In het onderstaande schema zie je een flowchart.
In dit voorbeeld wordt vanaf Groen wordt gestart. Dit wordt het welkomstscherm. Na het welkomstscherm komt het eerste deel van de game dat verhaal bevat. Na het verhaal komt een keuze. Bij een slechte keuze komt er een eind scherm, en ga je daarna terug naar het welkomstscherm. Bij de goede keuze gaat het volgende deel van het verhaal verder. DIt leidt tot de volgende keuze, die als gevolg een goed en een slecht einde hebben. Beiden brengen je terug naar het welkomstscherm.
Visuals en Layout
Belangrijk is het volgende. Hoe komt de game eruit te zien. Waar staat de informatie voor de speler? Hoe heeft de speler interactie met de game? Dit moet duidelijk gaan worden voordat er gewerkt kan gaan worden aan de game.
Uitwerking Game design voor deze tutorial.
In deze tutorial gaan wij als eerst aan de slag met een ouderwetse Textadventure game. Om uit te leggen hoe deze game gaat worden, wordt de Game Design hier uitgelegd. Er zijn vele principes om de Game design uit te leggen, maar deze gaan wij nu nog niet uitgebreid behandelen. Voor nu houden wij het simpel om de bedoeling van deze game uit te leggen. Je kan simpelweg zeggen dat bij Game Design twee principes worden behandeld. De intentie en de executie. Oftwel, wat willen wij gaan maken en wat wij uit eindelijk maken. De intentie die wij hebben is als volgt:
Player Experience
De speler moet zich gaan voelen als een old school gamer. In het begin waren games tekst gebaseerd. Door middel van tekst werd uitgelegd waar de speler zich bevond en wat de reactie op zijn acties was. Door commando's in te typen had de speler interactie. Een simpel voorbeeld is Zork.
Core Mechanic
Door het verhaal en de wereld te verkennen moet de speler de juiste keuzes maken. De speler leest wat er zich bevindt in de wereld en kiest je juiste reactie.
Core game loop
De speler wordt geconfronteerd met de omgeving en moet hierbij keuzes maken, door te gokken of goed de omgeving te verkennen. Keuzes kunnen tot goede of slechte eindes werken.
Gameflow
Hoe gaat de game verlopen. De game moet verschillende keuzes gaan bevatten. Keuzes die tot verschillende eindes kunnen komen. Om dit heel simpel weer te geven, gebruik ik deze flowchart:
Vanaf Groen wordt gestart. Dit wordt het welkomstscherm. Na het welkomstscherm komt het eerste deel van de game dat verhaal bevat. Na het verhaal komt een keuze. Bij een slechte keuze komt er een eind scherm, en ga je daarna terug naar het welkomstscherm. Bij de goede keuze gaat het volgende deel van het verhaal verder. DIt leidt tot de volgende keuze, die als gevolg een goed en een slecht einde hebben. Beiden brengen je terug naar het welkomstscherm.
Visuals en Layout
Belangrijk is het volgende. Hoe komt de game eruit te zien. Waar staat de informatie voor de speler? Hoe heeft de speler interactie met de game? Dit moet duidelijk gaan worden voordat er gewerkt kan gaan worden aan de game.
Vervolgstap 1: Assets importeren
Game assets, of soms ook kort assets genoemd, zijn de onderdelen waarmee wij de game gaan bouwen. Dit kan zijn 3D modellen van bomen, 2D sprites van auto's, geluiden van een geweer of scripts om iets te laten werken. Aangezien wij nog niet zover zijn om deze zelf te maken, gaan wij bestaande assets gebruiken voor onze game. Er is een pakket klaar om te downloaden en deze in het project te importeren.
WM2000 Package.unitypackage
DIt is een archive bestand. Deze bevat meerdere bestanden die te gebruiken zijn als assets en is bedoeld om in Unity te gebruiken. Als je Unity aan hebt staan, en je dubbelklikt op het gedownloade bestand, zal er een Import Window openen in Unity.
Voor nu gaan wij er niet precies op in wat al deze bestanden inhouden. Het is voor nu belangrijk dat alles belangrijk is om te gebruiken, dus vink niks uit en klik op de knop Import. Na een korte tijd is alles klaar met importeren. In de Project Window is een map verschenen genaamd WM2000. In deze map staan de volgende bestanden:
Bij één van deze bestanden zie je een blauwe box als icoon, genaamd een Prefab. Pak dit bestand op door erop te klikken met de linkermuisknop en deze vast te houden, en los te laten in de Hierarchy.
Door dit in de hierarchy window te slepen, gebeurt er iets in de Scene View. Er is daar een weergave van een terminal verschenen. Door de game te runnen zal je zien dat wij gelijk een werkende terminal hebben voor de game.
Vervolgstap 2: Eerste keer coderen
Het moment is aangekomen om ons eerste C# script aan te maken. In de Project Window, klik met de rechtermuisknop ergens in deze window, ga naar Create, vervolgens Folder. Noem deze Scripts. Het is belangrijk om met een structuur te werken. Wij maken daarom een aparte map aan om onze scripts in te plaatsen.
Dubbelklik op de map om deze te openen. Hierin maken wij een nieuw leeg C# script. Opnieuw rechtermuisknop, Create, en nu C# Script. Noem het script MyAdventure.cs.
Open het script door erop te dubbelklikken.
Het script begint met de eerste drie regels. Heel belangrijk zijn deze maar waarom? Dat vraagt om aardig wat uitleg. Voor nu is het belangrijk om te weten dat wij alleen bepaalde zaken in de code kunnen aanroepen, omdat deze regels hierboven ervoor zorgen dat de desbetreffende bibliotheken (libraries) worden ingeladen. Laten wij verder kijken naar de rest van het script.
Er wordt gedefineerd wat de class is van deze code. Controlleer of deze dezelfde naam heeft als de naam van het bestand. Wat een class verder inhoudt behandelen wij op een later moment.
Je zal zien dat onze class standaard twee methodes heeft, soms ook functies genoemd. De start en de update. Unity heeft veel methodes die standaard aanwezig zijn en aangeroepen kunnen worden, maar deze twee worden automatisch in een script voor jou geplaatst. De Start() wordt door Unity aangeroepen eenmalig wanneer het gameobject zich bevindt in de Scene. De Update() wordt continue aangeroepen, 1 keer per frame. Draait de game met 60 frames per seconde (fps), dan zal de update ook 60 keer per seconde worden uitgevoerd. Voor nu gaan wij alleen in Start() aan de slag.
Wij gaan onze eerste code typen. Typ de tekst print("Hello World!");
Sla het script op. Ga terug naar de Unity Editor. Voordat ons script uitgevoerd kan worden, moet het een onderdeel worden van de Scene. Dit doen wij door het script in de Project Window op te pakken en te slepen naar het WM2000 Object in de hierarchy. Als dit goed gaat, verschijnt het script als een onderdeel van dit object als deze is geselecteerd en de Inspector bekeken worden.
Nu kan het script getest worden. Druk op de Play knop en houdt de console window in de gaten.
De console window is de manier hoe wij een vinger aan de pols kunnen houden wanneer er wordt gewerkt aan de game. Berichten, waarschuwingen en fouten worden hier geplaatst. Tijdens deze test hebben wij alleen een bericht laten plaatsen. Ga terug naar de code en voeg een extra regel toe.
Sla het opnieuw op en ga terug naar de Unity Editor. Klik weer op de Play knop en zie het resultaat.
Vervolgstap 3: De eerste functies
In de vorige stap werd op het einde wat basisprincipes van programmeren in C# uitgelegd. Voordat wij verder kunnen op deze pagina behandelen wij nog wat extra zaken. Wij gaan namelijk beginnen om onze eerste functies schrijven. Functies binnen in classes zijn eigenlijk methods, afgeleid van C++, maar wij blijven de algemene term functies wel gebruiken. Een functie bevat zelf weer één of meerdere statements, code dat uitgevoerd moet gaan worden. Daarboven, de class zelf, bevindt weer in een namespace, soms ook een library genoemd. Oftwel, van groot naar klein, praten wij over: Namespace, Class, Function, Statement. Zie het plaatje hieronder.
Laten wij doorgaan over functies. Een functie kan vergeleken worden met een contract. Het bevat zaken die moeten gaan gebeuren als deze wordt aangeroepen. Wij beginnen in ons eigen script een eigen functie te maken zoals hieronder.
Tussen de Start() en Update() is de functie ShowMainMenu() toegevoegd. Iets meer uitleg over deze eerste regel
void - ShowMainMenu - ()
Het eerste woord, void, beschrijft wat de functie als antwoord teruggeeft wanneer deze aangeroepen wordt. Voor nu gaan wij hier nog niet verder op in. Voor nu moet je weten dat void 'niets' betekent, oftewel de functie geeft geen antwoord terug.
Het tweede woord, ShowMainMenu, is een zelf verzonnen naam. Namen van functies mogen wij zelf verzinnen, zolang deze maar niet met een getal beginnen. Verder is het verstandig geen naam te namen die je al eerder heb gebruikt, of door Unity al wordt gebruikt (zoals Start en Update). Wanneer je zelf een naam verzint, zorgt er dan voor dat de naam beschijft waar de functie voor gaat worden gebruikt. Dat is handig voor jezelf, maar ook anderen ook moeten lezen. In dit geval is ShowMainMenu duidelijk wat het moet gaan doen. Wat dan? Het Main Menu laten zien!
Het laatste deel zijn de (), de parameter. Nu is het leeg. Hier kan je een waarde meegeven aan de functie mocht deze het nodig hebben bij uitvoeren. Omdat het nu bij ShowMainMenu niet nodig is, is de ruimte tussen de haakjes leeg.
Nu je meer begrijpt wat de woorden inhouden, kan de functie ook echt gevuld gaan worden.
De eerste regel met ClearScreen, zal alle eerdere geschreven tekst verwijderen. Daarna worden er 3 regels geschreven dat de speler welkom heet en uitlegt hij de game gestart moet worden. Standaard zal een functie niet zomaar aangeroepen worden. Omdat wij willen dat dit gelijk gebeurd wanneer het spel opgestart wordt, roepen wij de functie aan vanaf Start() zoals hieronder.
Zoals je kan zien, wij hoeven alleen de naam te schrijven van de functie. Test het uit door het script op te slaan, terug te gaan naar de Unity Editor en op de Play knop klikken.
De regels staan nu in de terminal. Je ziet dat dankzij de assets die wij gebruiken, de regels al automatisch enters krijgen. Ook als een regel te lang is, zoals de tweede, dan gaat hij automatisch verder op de volgende regel. Nu wij het beginsel hebben, kunnen wij op de volgende pagina verder om ook input uit te lezen.
Vervolgstap 4: UserInput en C# operators
Nu wij teksten kunnen krijgen op het terminal scherm, kunnen wij naar de volgende stap om te reageren wat de speler schrijft. Het is voor ons al makkelijk gemaakt door de bestaande assets die wij hebben geïmporteerd. Door simpel de functie OnUserInput aan te maken, zal deze worden uitgevoerd wanneer de speler op de return knop drukt. De laatst ingetype tekst worden dan opgenomen. Het ziet eruit zoals hieronder.
Deze keer is het anders dan wanneer wij ShowMainMenu hadden gemaakt. Deze keer is de parameter wel gevuld. Het wilt een variabele van het type string die wij input noemen. Zie een variabele als een emmer waar wij data in kunnen stoppen.
De data kan van alles zijn. Een stukje tekst, een getal, etcetera. Hieronder staat een kort lijstje met verschillende type data die vaak voorkomen:
- string: tekst;
- integer (int): hele getallen;
- float: komma getallen;
- boolean (bool): waar of niet waar;
Een string betekent dat het tekst is. Integer staat voor hele getallen, deze mogen ook negatief zien. Een float mogen zowel hele als komma getallen zijn zoals 3,5 en mag eventueel negatief zijn. Een boolean is een aparte, hierin bewaar je of iets WAAR of NIET WAAR is, oftwel true of false. Het is voorkomend om op te geven wat voor soort data een variabele mag bevatten. Mocht je dit niet willen, omdat je niet van tevoren weet wat je erin gaat stoppen, kan je er de afkorting var voor neerzetten. Het mooie van een variabele is, is dat de data makkelijk gebruikt kan worden wanneer de naam van de variabele gebruikt wordt. Een simpel voorbeeld hieronder.
Hier wordt print gebruikt, om de inhoud van input in de console neer te zetten. Als het script wordt opgeslagen, en de kan wordt gestart in de unity editor, kan er een wordt worden getypt en op de return knop worden gedrukt. Hetzelfde wordt zal dan in de console verschijnen zoals hieronder.
Het handige van een variabele is, wij kunnen de data ondertussen aanpassen. Oftewel, er mag iets anders intussen in de emmer gestopt worden.
De inhoud wordt zogezegd vernieuwd met nieuwe data. Laten wij dit ook eens proberen.
De regel ziet er een beetje raar uit als je er wiskundig naar kijkt. Wij zeggen dat de waarde van input moet veranderen door de tekst 'de geschreven data is : ' en voegen door middel van het + teken ook de oude data van input eraan vast. Door het op te slaan en opnieuw uit te testen krijgen wij het onderstaande resultaat.
Operators
Nu er een begrip is hoe variabelen werken, kunnen wij over naar de volgende stap welke wij operators noemen. Zonet hadden wij het al eentje gebruikt, de + oftewel Plus operator. Eerder werd het gebruikt om twee string aan elkaar vast te maken om in een variabele te stoppen. Hieronder staat een simpel tabelletje dat beschrijft wat het kan doen:
Als wij dus een + tussen twee strings zetten, worden deze samen één nieuwe string. Tussen twee getallen, oftewel integers of floats genaamd, dan worden ze bij elkaar opgeteld. Wanneer een string en een int/float met een + worden verbonden, wordt van de int/float een string gemaakt en worden beide string aan elkaar vastgemaakt in één nieuwe string.
Een andere operator is de == operator. Het wordt gebruikt om variabelen of data met elkaar te vergelijken of deze hetzelfde zijn. Hieruit gaat een boolean komen, die aangeeft true of false oftwel waar of niet waar. Waar als beiden hetzelfde is of niet waar als beiden niet hetzelfde zijn. Hieronder een tabelletje met wat voorbeelden. Een cijfer wordt als tekst beschouwd met " " tekens, oftewel een string.
Bij de laatste komt niks, geen true of false. Het wordt namelijk een foutmelding, omdat een string en een int/float niet met elkaar vergeleken kunnen worden. Het zijn andere type data. Alles wat de speler zal typen, komt binnen als een string (tekst). Wanneer wij willen gaan controlleren wat de speler heeft getypt, zal het string data moeten zijn waarmee wij gaan kijken, zoals in onderstaande voorbeeld.
Hiermee krijg je het volgende in de Unity Editor
Er is een 1 getypt, wordt gezien als een string die is opgeslagen onder input. DIt wordt vergeleken met de waarde "1". Als deze hetzelfde zijn, wordt er True neergezet in de console. Op de volgende pagina gaan wij verder met if-statements.
Vervolgstap 5: Gameflow met if
Eerder is al even het onderwerp gameflow behandeld. Met de gameflow moet duidelijk worden hoe de game gaat verlopen. Om te weten hoe de game wordt gebouwd, kan je hiervoor even terugscrollen naar gameflow. Als je de flowchart bekijkt, zie je dat er verschillende keuzes zijn die de speler kan maken. Deze keuzes moeten worden getypt, de functionaliteit waar wij in de vorige hoofdstukken mee bezig waren. Om te controleren wat de speler heeft ingevoerd, gaan wij aan de slag met if statements.
Een if statement werkt als volgt. Er wordt een stukje code uitgevoerd, als er aan een voorwaarde wordt voldaan. Heel simpel. Eventueel kan je meerdere en/of alternatieve voorwaardes opgeven. Simpel voorbeeld hier onderin.
De voorwaarde in de if statement is dat het woord start moet zijn. Als dit ook zo is, dan wordt de nieuwe functie StartIntro() gestart. Deze functie houdt simpelweg in dat het scherm wordt geleegd en nieuwe tekst op het scherm komt. Dit is nog een simpele, want er zijn geen alternatieve voorwaarden opgegeven. Met een alternatieve voorwaarde wordt het als volgt.
Door else if erachteraan te zetten, gaat de compiler deze voorwaarde controleren, als er niet aan de eerdere voorwaarde voldaan wordt. Het is dus een andere controle, die pas wordt gedaan als de eerste niet door is gekomen. Je kan ook een alternatieve actie opgeven zonder een voorwaarde. Dat gebeurd als volgt.
Door een else te schrijven, gaat dit gebeuren als er niet aan de eerste voorwaardes in de if statement werd voldaan.
Voor deze game gaan wij een specifieke techniek gebruiken om het overzicht makkelijk te maken. Dat is een Finite State Machine. Met een FSM kunnen wij alle mogelijke states opgeven door voor kunnen komen, en afhankelijk van de state gaan wij bepaalde acties laten uitvoeren. Een FSM maken wij met een enumerator. Dit doen wij als volgt.
Bovenin de class maken wij een enumerator aan genaamd States. Deze bestaat uit de states die je vervolgens daaronder ziet op een rijtje. Elke state wordt gescheiden met een komma. Om bij te houden wat de huidige state is, wordt als laatst een variabele gemaakt op basis van de eerder gemaakte States genaamd currentState. De huidige state wordt meteen gezet op start. Nu moet er pas op bepaalde invoer gecontroleerd gaan worden, wanneer een bepaalde state actief is. Dit doen wij zoals hieronder.
Met een else if geven wij een alternatieve voorwaarde. Daarmee controleren wij nu of de state intro1 is. Zo ja, dan kan er worden gekeken of de speler het woord verder heeft getypt, nodig om verder te kunnen met het verhaal. Maar voordat je verder met het verhaal aan de slag gaat, kijken wij nog heel even naar een alternatief op if statements, namelijk een switch. Aan het begin wordt eerst switch genoemd, en tussen haakjes de variabele die gecontroleerd moet worden. Vervolgens wordt met case opgegeven wat de waarde zou moeten zijn, voordat de rest van de code wordt uitgevoerd. Belangrijk dat elke case altijd met een break moet worden afgesloten. Een extra case ziet er als volgt uit.
Dit is zoals je ziet een andere manier om te kunnen controleren op zaken. Maar wat is nou beter? Het maakt niet zoveel uit. Wel is het verstandig om met het volgende rekening te houden:
- Gebruik een if als je een logische vraag stelt
- Wees voorzichtig met een if want de volgorde is belangrijk
- Bedenk of je een switch wilt gebruiken wanneer je op waardes controleert
- Volgorde op vergelijken is niet belangrijk bij een switch
- Vergeet geen break te gebruiken in een switch
- Een if is overal te gebruiken mocht je dat willen
Einde tutorial
Nu je een stevige basis hebt, kan je aan de slag om de game af te maken! Succes! Ik hoop dat je wat hebt gehad aan deze tutorial, een grote kans is dat er wat spellingsfouten in staan, geef deze gerust aan zodat ik dit kan verbeteren. Heb je over het algemeen tips, laat dit dan ook weten!
Andere leuke units, uitgelegd door Unity zelf.
Unit 1: https://learn.unity.com/tutorial/set-up-your-first-project-in-unityuv=2018.4&courseId=5cf96c41edbc2a2ca6e8810f&projectId=5caccdfbedbc2a3cef0efe63
Unit 2: https://learn.unity.com/project/unit-2-basic-gameplay?courseId=5cf96c41edbc2a2ca6e8810f
Unit 3: https://learn.unity.com/tutorial/lesson-3-1-jump-force?courseId=5cf96c41edbc2a2ca6e8810f&projectId=5cf9639bedbc2a2b1fe1e848
Unit 4: https://learn.unity.com/tutorial/lesson-4-1-watch-where-you-re-going?courseId=5cf96c41edbc2a2ca6e8810f&projectId=5cf96846edbc2a2bcde6d0fc
Groet,
Mitchel