Inhoud
- Wat vooraf ging
- Inleiding
- Blueprints Visual Scripting
- Hello World!
- Licht aan bij het opstarten
- Licht aan bij het binnengaan en uit bij het verlaten
Wat vooraf ging
- U bent vertrouwd met de begrippen Programmeren en programmeertalen.
Inleiding
U hebt reeds een idee van wat programmeren is en we gaan nu ons eerste eenvoudig programmaatje maken.
In deze Start To Program reeks is gekozen voor de 3D omgeving van Unreal Engine om kennis te maken met het programmeren.
Ik ga ervan uit dat Unreal Engine geïnstalleerd is op uw pc (lees hier hoe u het kunt installeren).
- Start Epic Games Launcher.
- Klik op Launch om Unreal Engine te starten.
- Start een nieuw Third Desktop/Console project van Maximum Quality With Starters Content en geef het een passende naam.
Blueprints Visual Scripting
Misschien eerst nog even een eenvoudige definitie van programmeren aanhalen:
Programmeren is de computer dingen laten doen door het specifieke instructies te geven in een programmeertaal.
Deze instructies worden gegeven in een programmeertaal.
C++ is al vele jaren de belangrijkste programmeertaal voor 3D-applicaties en is ook de programmeertaal die Unreal Engine gebruikt.
C++ is echter geen toegankelijke programmeertaal en is dus niet eenvoudig om aan te leren. Om het programmeren toegankelijker, eenvoudiger te maken voor beginnende programmeurs heeft EPIC, de firma achter Unreal Engine, Blueprints Visual Scripting toegevoegd aan C++.
Blueprints Visual Scripting heeft volgende voordelen:
- C++ is nog steeds de achterliggende programmeertaal met al zijn kenmerken en voordelen. U leert dus, net als in C++, programmeren met variabelen, objecten, eigenschappen, methoden, events, selecties, lussen, arrays, klassen, interfaces, overerving,… kortom u leert volwaardig programmeren.
- Blueprints Visual Scripting is speciaal ontwikkeld voor ontwikkelaars zonder programmeerervaring en dus ook voor de startende student.
- U schrijft geen programmeercode meer maar u verbindt visueel de instructies via nodes. Dit heeft als belangrijkste voordeel dat u zich niets meer moet aantrekken van de syntax, de schrijfwijze van een programmeertaal, maar dat u zich volledig kunt concentreren op de logica, de volgorde van de instructies.
U kunt Blueprints maken op 2 niveaus:
Level Blueprint – Iedere level van het spel/programma komt met zijn eigen Level Blueprint. Wat u programmeert binnen deze Level Blueprint is enkel gekend/bruikbaar binnen dit level zelf. De Level Blueprint heeft o.a. toegang tot alle actors (objecten binnen een level) en kan communiceren met Blueprint Classes die aan het level toegevoegd zijn.
Blueprint Class – Een Blueprint Class wordt gebruikt om objecten interactief te maken, om functionaliteiten toe te voegen aan een bestaande objecten. Bv. een deur is een objecten. Om de deur te openen zijn er instructies nodig, moet er geprogrammeerd worden. Dit kan via een Blueprint Class.
Een Class (of klasse) is een typisch begrip binnen object georiënteerd programmeren (OOP) en we gaan dit pas later bespreken. We beperken ons dus voorlopig tot Level Blueprint
Hello World
Iedere zichzelf respecterende programmeercursus begint met een “Hello World” programmaatje.
We doen hetzelfde, we wensen dat bij het opstarten van ons programma, meer specifiek ons level, we een “Hello World” boodschap krijgen.
Level Blueprint
We hebben reeds gezien dat we gaan programmeren gebruikmakend van Blueprints en dat er zoiets bestaat als een Level Blueprint die de Blueprint, de programmeercode, bevat horende bij het level.
- Om de Level Blueprint te openen klikt u in de knoppenbalk van de Viewport op Blueprints – Open Level Blueprint.
De Level Blueprint wordt geopend in de zogenaamde Event Graph. De Level Blueprint kent enkel maar deze Event Graph.
In de Events Graph worden de events geprogrammeerd.
Events
Een event is een gebeurtenis, iets dat kan plaatsvinden, die getriggerd wordt door het systeem of door de gebruiker.
Een klassiek voorbeeld is het klikken op een knop. Het klikken op een knop triggert de Click-event horende bij die knop.
In Level Blueprint ziet u reeds twee events klaar staan (al zijn ze beiden nog grijs want geen van beiden is momenteel verbonden met een instructie):
- BeginPlay – deze event wordt uitgevoerd wanneer het spel start (voor de actor, in het meeste geval voor de speler).
- Tick – Deze event wordt iedere frame uitgevoerd (bij 60 fps (frames per second) dus 60 keer per seconde).
Merk op dat beiden events dezelfde stijl hebben (rode bovenrand). Alle events gebruiken deze stijl en zijn zo meteen herkenbaar als events.
Print “Hello World”
Als het level start, de speler begint te spelen, dan moet de tekst “Hello World” op het scherm getoond worden.
“Als het level start, de speler begint te spelen” met andere worden als de BeginPlay-event getriggerd wordt.
Blueprint Visual Scripting werkt op basis van nodes die verbonden worden.
Nodes worden met mekaar verbonden via de Exec-pin.
- We vertrekken vanuit de BeginPlay-node en slepen nu vanuit de Exec-pin, met de linkermuisknop ingedrukt, een verbindingslijn.
We wensen de tekst “Hello World” af te printen. Een tekst wordt een String genoemd in vele programmeertalen en ook in Unreal Engine.
- Zoek naar de actie, de functionaliteit (functie), aangeduid met een F “Print String”. Typ hiertoe “print” en u vindt de functie “Print String”.
- Klik op Print String. De functie wordt als een node toegevoegd en verbonden met de BeginPlay-node.
Merk op dat daar waar events met een rode omkadering worden weergegeven, functies in een blauwe omkadering worden weergegeven.
Merk eveneens op dat de functie Print String enkel zal werken in Development only en niet in de eigenlijke, finale versie van het programma. Dit is oké, voor nu (we zien later betere technieken om tekst weer te geven).
- Wijzig de tekst “Hello” in “Hello World”.
- Klik op het pijltje onderaan in de functie-node Print String om meer opties te zien.
Merk op dat u standaard de tekst:
- print (toont) op het scherm.
- print in het logscherm.
- de tekstkleur lichtblauw is (kunt u wijzigen).
- de tekst 2 seconden wordt getoond.
We kunnen nu het level, het spel, starten maar eerst moeten we compileren.
- Klik op de knop Compile (druk op de toetsen Ctrl + Alt voor de extra uitleg) om de Blueprint te compileren.
- Klik in de knoppenbalk op Play (of druk op Play vanuit de Level Editor (zoals we het in de vorige handleidingen deden).
Gedurende 2 seconden verschijnt de lichtblauwe tekst “Hello World” in de linker bovenhoek.
Echt geweldig is het nog niet maar het is wel ons eerste programmaatje.
Nodes verwijderen
Nu we ons allereerste programmaatje geprogrammeerd hebben gaan we plaats maken voor iets praktischer. Maar eerst gaan we de nodes verwijderen.
- Selecteer de node Print String en klik op de Delete-toets.
- Selecteer eveneens Event Tick en klik op de Delete-toets.
Enkel Event BeginPlay staat nog in de Level Blueprint.
Licht aan bij het opstarten
Als het level start, de speler begint te spelen, dan moet het licht branden.
In plaats van “Hello World” te zeggen willen we nu iets praktischer programmeren, maar nog steeds heel eenvoudig, namelijk “Als het level start, de speler begint te spelen, dan moet het licht branden”.
Maar eerst moeten we even stilstaan bij het begrip objectgeoriënteerd programmeren.
Objectgeoriënteerd programmeren
In een objectgeoriënteerde programmeertaal staan objecten centraal.
Een object is de basisbouwsteen bij object georiënteerd programmeren. Zowat alles is opgebouwd uit objecten.
In een 3D-omgeving is dit nog duidelijker omdat de objecten, meestal, visueel te zien zijn: muren, deuren, ramen, stoelen, tafels, bomen,… dit zijn allemaal objecten. Maar ook de karakters, lichten,… zijn in wezen objecten. Objecten die we kunnen plaatsen en transformeren in level worden ook actors genoemd.
Al deze objecten hebben eigenschappen en functionaliteiten.
Eigenschappen zijn kenmerken zoals hoogte, breedte, kleur,… die een waarde kunnen hebben.
Functionaliteiten (functies) zijn acties die met, op of door het object kunnen worden uitgevoerd. Denk aan lopen, springen, instorten, licht geven,… Functionaliteiten kunnen ook gebruikt worden om de correcte, gewenste waarden toe te wijzen aan de eigenschappen.
Licht toevoegen aan het level
Eerst gaan we een licht, meer bepaald een PointLight, toevoegen aan het level.
- Zoek links in het Modes-panel naar Lights – Point Light.
- Sleep de Point Light dit ergens in het decor van het level. U zou normaal het licht moeten zien branden.
Point Light is nu een zogenaamde actor in het level.
Eigenschappen
De actors, een actor is een object dat toegevoegd is aan een level, die toegevoegd zijn aan het level ziet u in de World Outliner. Als u een actor selecteert dan ziet u de eigenschappen, de kenmerken, van deze actor in het Detail-panel.
- Selecteer het toegevoegde PointLight en bekijk de eigenschappen.
Merk op dat de eigenschap Visible aangevinkt is. Inderdaad, als we het level starten brandt het licht reeds.
- Omdat we het licht willen laten branden via programmeercode vinken we de eigenschap Visible uit.
Blueprint Licht aan
- Open de Level Blueprint opnieuw door in de knoppenbalk van de Viewport op Blueprints – Open Level Blueprint aan te klikken.
We willen dat “Als het level start, de speler begint te spelen, het licht brandt”.
Concreet:
Als het spel start, Event BeginPlay, moet de eigenschap Visible van het object PointLight aan, op true, gezet worden.
We moeten dus de eigenschap van het object PointLight wijzigen, object georiënteerd, hiertoe moeten we eerst een referentie naar het object PointLight toevoegen aan Level Blueprint.
Referentie naar een object toevoegen
- Zorg dat het object PointLight geselecteerd is.
- Klik nu met de rechtermuisknop in de Level Blueprint.
- Omdat het object PointLight geselecteerd is kunt u nu klikken op Create a reference to PointLight.
De referentie naar het object PointLight, komende uit het Persistent Level, wordt toegevoegd aan Level Blueprint.
We moeten nu de eigenschap Visible van het object PointLight kunnen wijizgen.
- Sleep een verbindingslijn vanuit de PointLight-node en zoek naar Visibility.
U ziet verschillende opties verschijnen.
Toggle betekent: zet aan indien uit en uit indien aan (schakelen dus). Ik zou hiervoor kunnen kiezen en dit zal werken (onderstaande video doet dit).
Maar eigenlijk wil ik de eigenschap Visibility een andere waarde geven (Set). Ik kies dus voor Set Visibility.
Ik kan nu nog kiezen uit Set Visibility (Lightcomponent) of Set Visibility (PointLightcomponent). Omdat een PointLightcomponent eigenlijk ook een Lightcomponent is maakt ook dit geen verschil uit. Ik kies misschien het meest specifieke, in dit geval dus Set Visibility (PointLightcomponent).
- Klik op Set Visibility (PointLightcomponent).
- Versleep de nodes een beetje zodat het er overzichtelijker uitziet.
Merk op dat hij er automatisch een derde node heeft aan toegevoegd. Dit is de conversie (of casting) van ons PointLight naar het PointLightcomponent.
Oké, eigenlijk is deze conversie niet nodig want PointLight is reeds een PointLightcomponent maar C++, de achterliggende programmeertaal is nogal heel strikt en vraagt altijd de juiste conversie (ook al is het op zich niet nodig) en aangezien het automatisch gebeurt laten…
We zien dat de functionaliteit Set Visibility (merk de F op in de blauwe rand) een Target verwacht, het PointLightcomponent waarvoor de Visibility moet gewijzigd worden. Deze Target is reeds verbonden met ons object PointLight. De functionaliteit Set Visibility biedt ook de mogelijkheid een New Visibility in te stellen door het aankruisvakje aan te vinken.
- Vink New Visibility aan.
- Verbindt, via de Exec-pin, de event BeginPlay met de functie Set Visibility.
- Compileer het Level Blueprint door te klikken op de knop Compile. Vergeet dit niet!
- Build en start het level. Merk op dat het licht aan is (ok, dit was het daarvoor ook al maar nu hebben we het geprogrammeerd (How cool is that?).
Onderstaande video demonstreert het bovenstaande.
Licht aan bij het binnengaan en uit bij het verlaten
Als u, de speler, het “huisje” binnenstapt moet het licht aangaan, als hij het weer verlaat moet het licht weer uitgaan.
Opmerking, onderstaande tekst is “geleend” uit een uitgebreider voorbeeld waarin een “huisje” werd gebouwd. Bij het binnengaan van het huisje moest automatisch het licht aangaan, en bij het verlaten automatisch uit.
We gaan hier geen “huisje” bouwen, we gaan ons huisje vervangen door de “blok” (CubeMesh) reeds aanwezig in het level.
Eerst gaan we ons bestaande Level Blueprint moeten wijzigen. Het licht mag immers niet langer aan staan bij het starten van het level, het moet uit zijn bij starten van het level en pas aan als ik het “huisje” binnenstap.
- Open Level Blueprint.
- Vink New Visibility uit.
Triggerbox
Als we het huisje, die Box, binnen gaan moet het licht aan gaan.
We gaan dus iets nodig hebben waardoor het systeem weet dat het huisje wordt binnen gestapt en dat een event triggert (meer bepaald een Overlap-event).
We gaan dit simuleren met onze Box.
- Selecteer de Box.
- In het Detail-panel (rechts) wijzig de naam van de BoxMesh in TriggerBoxHuisje (dit is de naam die ik in de originele handleiding gebruikte en die u in onderstaande schermafbeelding zal zien).
Deze Box zal niet standaard Overlap-events triggeren, we gaan dit eerst even moeten instellen door de gewenste eigenschap in te schakelen.
- In het Details-panel, zoek naar Collision – Generate Overlap Events en vink dit aan.
Standaard kunt u de Box niet overlappen. Dit moet u ook instellen.
- In het Details-panel, zoek naar Collision – Collision Presets en kies uit de keuzelijst, voor het gemak, OverlapAll.
- Klik op Play.
En merk dat we het de Box kunnen overlappen, het “huisje” kunnen binnengaan.
Nu gaan we programmeren dat we door deze Box te overlappen het licht aan en uit kunnen schakelen.
Event OnActorBeginOverlap
De Event OnActorBeginOvelap wordt getriggerd wanneer we een bepaalde actor (TriggerBoxHuisje) overlappen. In ons voorbeeld moet dan het licht aangaan.
- Selecteer de Box.
- Ga naar Level Blueprint.
- Binnen Level Blueprint, klik met de rechtermuisknop in de editor. Met de TriggerBoxHuisje geselecteerd krijgt u een snelmenu.
- Klik op Add events for Trigger Box Huisje – Collision – Add on Actor Begin Overlap. Dit is de event die wordt getriggerd als een actor, ons karakter, de Box begint te “overlappen”.
Een nieuwe OnActorBeginOverlap-event is toegevoegd.
Als we deze TriggerBoxHuisje beginnen te overlappen, als we dus het huisje binnengaan, moet het licht aan gaan, of anders gezegd, moet de Visibility van object PointLight op true staan.
- Het object PointLight is reeds toegevoegd aan het level, we kunnen dit gewoon kopiëren en plakken.
- Sleep een verbindingslijn vanuit de PointLight-node en zoek naar Visibility.
- We kiezen echter deze keer voor Toggle Visibility, dit heeft ons een grotere herbruikbaarheid van de functie (zie hieronder).
Merk de gelijkenissen op met de functionaliteit Set Visibility.
Beiden ontvangen als Target het object PointLight dat eerst nog geconverteerd wordt naar PointLightComponent.
Toggle Visibility zal echter de Visibility automatisch veranderen van aan naar uit of omgekeerd. Er is dus geen setting van een New Visibility beschikbaar.
- Verbindt, via de Exec-pin, de event OnActorBeginOverlap met de functie Toggle Visibility.
- Compileer het Level Blueprint door te klikken op de knop Compile. Vergeet dit niet!
- Build en start het level, het licht is uit en gaat pas aan als u het “Huisje” binnenstapt, dus als u de TriggerBox begint te overlappen.
We hebben echter nog een probleem, het licht gaat wel aan als we het “Huisje” binnengaan, maar niet uit als we het “Huisje” verlaten. Als we dan opnieuw het “Huisje” binnengaan wordt het licht nu uitgedaan. Er wordt dus enkel mar geschakeld bij het binnengaan en niet bij het naar buitengaan.
Maar eerst gaan we nog een kleine pauze inlassen tussen het binnengaan en het licht dat aangaat.
Een delay (pauze) toevoegen
- Sleep een verbindingslijn vanuit de event OnActorBeginOverlap.
- Zoek naar de functionaliteit Delay.
Merk op dat deze nieuwe functie zich meteen plaatst tussen event OnActorBeginOverlap en de functie Toggle Visibility zodat er een continuïteit blijft bestaan in de volgorde van de instructies.
- Eerst een Delay
- Dan pas het licht schakelen.
- Eventueel kunt u nog de tijdspanne van de Delay (pauze) wijzigen door de eigenschap Duration te wijzigen naar bv. 0,5.
Event OnActorEndOverlap
We hebben echter nog een probleem, het licht gaat wel aan als we het “Huisje” binnengaan, maar niet uit als we het “Huisje” verlaten. Als we dan opnieuw het “Huisje” binnengaan wordt het licht nu uitgedaan. Er wordt dus enkel mar geschakeld bij het binnengaan en niet bij het naar buitengaan.
De oplossing is het licht eveneens te schakelen als het “Huisje” verlaten wordt. We hebben dus ook een event nodig die wordt getriggerd als de TriggerBoxHuisje wordt verlaten.
- Zorg er eerst voor dat TriggerBoxHuisje geselecteerd is.
- Binnen Level Blueprint, klik met de rechtermuisknop in de editor. Met de TriggerBoxHuisje geselecteerd krijgt u een snelmenu specifiek voor deze Triggerbox.
- Klik op Add events for Trigger Box Huisje – Collision – Add on Actor End Overlap. Dit is de event die wordt getriggerd als een actor, ons karakter, de Box beëindigt met te “overlappen”.
Een nieuwe OnActorEndOverlap-event is toegevoegd.
We kunnen nu identiek hetzelfde doen als bij OnActorBeginOverlap. Maar aangezien de nodes er toch staan kunnen we ze evengoed kopiëren en plakken.
- Selecteer alle nodes onder OnActorBeginOverlap, maak hiervoor gebruik van de Ctrl-toets.
- Kopieer en plak ze.
- Verbindt de gekopieerde Delay-functie met de OnActorEndOverlap-event.
- Compileer het Level Blueprint door te klikken op de knop Compile. Vergeet dit niet!
- Build en start het level.
Het programma werkt nu zoals gewenst.
Behandelde Basiscompetenties uit de module ICT Programmeren – Start to program
- IC BC228 – kent de verschillende principes en onderdelen op basis waarvan een programma kan opgebouwd worden
- IC BC229 – begrijpt de basisprincipes van programmeren
- IC BC237 – kan een eenvoudig programma wijzigen
- IC BC240 – kan een eenvoudig programma maken
- IC BC352 – begrijpt het systeem en de functies die achter een programma zitten