Inhoud
- Wat vooraf ging
- Gebruikte terminologie
- Inleiding
- Wat is een Gameplay Framework?
- Levels
- Actors
- Pawn, Controller en Character
- GameMode, GameState en Game Instance
- Project Twin Stick Shooter – Framework Review
- Masterclass
Wat vooraf ging
- U bent vertrouwd met de werkomgeving van Unreal Engine.
- U bent vertrouwd met object georiënteerd programmeren.
Gebruikte terminologie
Project
A Project is a self-contained unit that holds all the content and code that make up an individual game and coincides with a set of directories on your disk.
Objects
The base building blocks in the Unreal Engine are called Objects and contain a lot of the essential “under the hood” functionality for your game assets. Just about everything in Unreal Engine 4 inherits (or gets some functionality) from an Object.
Actors
An Actor is any object that can be placed into a level. Actors are a generic Class that support 3D transformations such as translation, rotation, and scale. Actors can be created (spawned) and destroyed through gameplay code (C++ or Blueprints).
Classes
A Class defines the behaviors and properties of a particular Object used in the creation of an Unreal Engine game. Classes are hierarchical, meaning a Class inherits information from its parent Classes (the Classes it was derived or “sub-classed” from) and passes that information to its children. Classes can be created in C++ code or in Blueprints.
Blueprints
The Blueprints Visual Scripting system in Unreal Engine is a complete gameplay scripting system based on the concept of using a node-based interface to create gameplay elements from within Unreal Editor. As with many common scripting languages, it is used to define object-oriented (OO) classes or objects in the engine. As you use UE4, you’ll often find that objects defined using Blueprint are colloquially referred to as just “Blueprints.”
Level
A Level is a user defined area of gameplay. Levels are created, viewed, and modified mainly by placing, transforming, and editing the properties of the Actors it contains. In the Unreal Editor, each Level is saved as a separate .umap file, which is also why you will sometimes see them referred to as Maps.
Components
A Component is a piece of functionality that can be added to an Actor. Components cannot exist by themselves, however when added to an Actor, the Actor will have access to and can use functionality provided by the Component. For example, a Spot Light Component will allow your Actor to emit light like a spot light, a Rotating Movement Component will make your Actor spin around, or an Audio Component will make your Actor able to play sounds.
Pawns
Pawns are a subclass of Actor and serve as an in-game avatar or persona, for example the characters in a game. Pawns can be controlled by a player or by the game’s AI, in the form of non-player characters (NPCs).
Controller
Controllers are non-physical Actors that can possess a Pawn (or Pawn-derived class like Character) to control its actions. A PlayerController is used by human players to control Pawns, while an AIController implements the artificial intelligence for the Pawns they control.
Inleiding
Gameplay Framework integreert alle onderdelen in een samenwerkend geheel. We gaan in deze handleiding stil staan bij het Gameplay Framework van Unreal Engine en herhalen een aantal bekende begrippen zoals Level, Actor,… maar vanuit hun plaats binnen het Gameplay Framework.
Situering van deze handleiding binnen Unreal Engine
Merk op, uit het schematisch overzicht, dat alle basisklassen van het Framework in C++ geschreven zijn. Dit heeft echter geen invloed op het gebruik ervan.
Wat is een Gameplay Framework?
Een Gameplay Framework:
- biedt een verzameling van basisklassen. Via overerving (inheritance) kunt u deze aangeleverde basisklassen gebruiken om verder op te bouwen.
- voorziet een basisstructuur en basisfuncties.
- biedt oplossingen voor veel voorkomende problemen (zoals character movement, multiplayer,…) zodat u het wiel niet steeds opnieuw hoeft uit te vinden.
- wilt niet alles aanbieden, zo biedt een Gameplay Framework van Unreal Engine geen oplossingen voor bv. wapensystemen, “health” en “death” omdat deze vaak project specifiek zijn en niet kunnen worden veralgemeend.
De keuze van het projecttype bepaalt mede het Gameplay Framework.
De keuze van het Project-type bepaalt het Gameplay Framework
- U begint met het gewenste project te kiezen.
Unreal Engine komt met een aantal Templates, u zou kunnen stellen, met een aantal Gameplay Frameworks.
Ieder project komt met eenzelfde basis maar met project specifieke content en Blueprints. Door de keuze van het type project bepaalt u met welk Gameplay Framework u start.
Laten we 2 verschillende projecten als voorbeeld nemen, het ThirdPerson-project en het Flying-Project.
- Het ThirdPerson-project staat wellicht al open, anders moet u er één openen.
U vindt de specifieke content en Blueprints in de Content Browser.
Hieronder ziet u de specifieke Third Person Blueprints (u vindt deze onder Content – ThirdPersonBP – Blueprints).
- Open, door te dubbelklikken, ThirdPersonCharacter.
- Ga naar de Event Graph van de ThirdPersonCharacter Blueprint (wellicht staat u hier al).
U ziet reeds verschillende specifieke events geprogrammeerd staan.
- Open een Flying-project.
U vindt de specifieke content en Blueprints in de Content Browser.
Hieronder ziet u de specifieke Flying Blueprints (u vindt onder Content – FlyingBP – Blueprints).
- Open, door te dubbelklikken, FlyingPawn.
- Ga naar de Event Graph van de FlyingPawn Blueprint (wellicht staat u hier al).
U ziet reeds verschillende specifieke events geprogrammeerd staan en merk op dat deze anders zijn dan bij de ThirdPersonCharacter Blueprint.
U merkt dus dat de keuze van het project de keuze van een specifiek Gameplay Framework inhoudt.
Levels
Een project kan bestaan uit meerdere levels. Een level is een map, een (onderdeel van) een wereld.
U kunt een nieuw level toevoegen via:
- Ga naar het menu File – New Level….
- Kies het template voor het nieuwe level (bv. Default).
- Een default level komt reeds met een aantal standaard actors.
Level openen via Blueprint Visual Scripting
Als u een level wilt openen via programmeercode dan gebruikt u OpenLevel. U moet de naam van het level dat u wilt openen meegeven aan Level Name.
Actors
Wat is een actor?
- Een actor is een object (een entiteit) dat in een level kan geplaatst worden.
- Een actor bevat componenten (de bouwstenen waaruit de actor is opgebouwd).
- Actors, en enkel actors (of klassen die erven van de klasse actor), kunnen worden gerepliceerd over een netwerk.
- De transformatie (locatie, rotatie en schaal) van de actor wordt bepaald door een Root Component. Iedere actor heeft dus een Root Component (Scene Component) dat de transformatie-informatie (locatie, rotatie, schaal) van de actor bevat.
Een nieuwe actor aanmaken
Om een nieuwe actor aan te maken, of beter gezegd, om een nieuwe klasse op basis van de klasse Actor aan te maken, moet u een nieuwe Blueprint Class aanmaken.
Tip, voor u begint nieuwe klassen aan te maken kunt u het best eerst een nieuwe folder aanmaken waarin u al uw eigen aangemaakte klassen bewaart.
- In de Content Browser, klik op Add New – New Folder.
Er zijn verschillende manieren om een nieuwe klasse aan te maken.
- In de Content Browser, klik op Add New – Blueprint Class (of klik met de rechtermuisknop in een folder en klik op Blueprint Class).
- Of, klik in het menu op Blueprints – New Empty Blueprint Class….
U komt in onderstaand scherm waar u een Parent Class kunt selecteren. Bovenaan vindt u de meest gebruikte Parent Classes, onderaan kunt u eventueel een specifieke klasse zoeken (nadien verschijnt een knop Select om deze specifieke klasse als Parent Class te selecteren).
- Klik op Actor.
- Geef de klasse een naam (bv. TestActor).
- Dubbelklik de klasse om deze te openen.
U ziet hier de reeds aanwezige Root Component (DefaultSceneRoot).
Een actor kan uitgebreid worden door componenten toe te voegen, maar het is de Root Component (DefaultSceneRoot), weergegeven door die witte bol, die de transformatie (locatie, rotatie en schaal) van de actor bepaalt.
Actors aanmaken en verwijderen via Blueprint Visual Scripting
Actors kunnen tijdens het bouwen van het level gewoon geplaatst worden in het level. Maar het kan ook gebeuren dat een actor moet worden aangemaakt ten gevolgen van een bepaalde event in het programma. Dan moet u de actor aanmaken via programmeercode, meer bepaald via Blueprint Visual Scripting.
De instructie die u moet gebruiken om een actor te laten verschijnen (spawnen) is SpawnActor. Vervolgens moet u de naam van de klasse meegeven van de actor die moet spawnen en de transformatie (locatie, rotatie en schaal) waar u wilt spawnen.
Wilt u een actor verwijderen uit een level (actors worden automatisch uit het geheugen verwijderd als een level wordt afgesloten), dan gebruikt u DestroyActor. U moet bepalen welke actor moet verwijderd worden via Target.
Alle actors van een specifieke klasse opvragen
Om alle actors van een specifieke klasse te selecteren zoekt u naar de functionaliteit Get All Actors Of Class. Het resultaat is een array met alle actors van de opgegeven klasse.
ActorComponent
Moest een actor enkel en alleen maar uit de Root Component (DefaultSceneRoot) bestaan, u zou er niet veel mee kunnen doen. Een actor is dan ook altijd opgebouwd uit meerdere componenten, de ActorComponent(en).
- Een actor bevat een Root Component (Scene Component) dat de transform-informatie (locatie, rotatie en schaal) en attachement-informatie van de actor bevat.
- PrimitiveComponent voegt collision-informatie en render-informatie toe.
- MeshComponent voegt materialen toe.
- Deze componenten voegen herbruikbare functionaliteiten toe aan de actor.
- Deze componenten bevatten gebeurtenissen (events) die kunnen getriggerd worden en waar instructies (programmeercode) kan aan gekoppeld worden.
Componenten van andere Blueprints bekijken
- Dubbelklik Blueprint_CeilingLight om deze te openen. Deze klasse kan gebruikt worden om “hangende lamp”-objecten toe te voegen.
- Klik op het tabblad Viewport. Hier vindt u de onderdelen, de componenten, waaruit deze klasse bestaat.
In het Components-panel ziet u eveneens de componenten en kunt u er nog anderen aan toevoegen.
De componenten van Blueprint_Wallsconce zijn bijna identiek aan de constructor van Blueprint_Ceilinglight. Er wordt gewoon een andere StaticMesh gebruikt die tegen een muur kan worden geplaatst.
De componenten van ThirdPersonCharacter zijn anders.
U ziet een CapsuleComponent als basis. De Capsulecomponent bevat een Mesh (het eigenlijke karaktermodel (de Mannequin)) en een ArrowComponent (die blauwe pijl die de kijkrichting van het karakter aanduidt) bevat. Verder is er ook een FollowCamera toegevoegd die zich achter het karakter bevindt (en zo voor de ThirdPersonCharacter-view zorgt). De camera hangt vast aan een zogenaamde CameraBoom.
Omdat ons ThirdPersonCharacter moet kunnen bewegen heeft het ook nog een CharacterMovement-component.
Pawn, Controller en Character
Pawn
Een pawn is een actor dat kan gecontroleerd worden door de speler of door AI (Artificiële Intelligentie).
- Het is de fysische representatie (“agent”) van een speler of een NPC (Non-player character).
- Een pawn bepaalt niet enkel het fysische uiterlijk (van de speler) maar ook de interactie met de omgeving.
- Een pawn kan, maar moet niet, bestuurd worden door een controller. Het is de pawn die de invoer (input) afhandelt.
- Een pawn verzorgt de verplaatsing (movement) maar komt zonder programmeercode die deze verplaatsing verzorgt.
- De pawn is een goede plaats voor het bijhouden karakter gerelateerde informatie zoals zijn “health”,…
Controller
- Een controller “bezit” (“possess”) the pawn.
- Een controller kan een speler (PlayerControler) of AI (AIController) zijn. De PlayController is de wil van de speler, de AIController de wil van de NPC’s (zeg maar de AI van het spel).
- Een controller bezit maar één pawn tegelijkertijd.
- Een controller kan blijven bestaan als de pawn “sterft” (dit maakt een “respawn” mogelijk).
- Een controller regelt zaken als weergave van de HUD, muiscursor (muisinterface), cheatmanager,…
Character
Een character is een speciale pawn waaraan “charactermovement” is toegevoegd.
- De Character-klasse erft van de pawn-klasse en heeft dus alle kenmerken van een pawn.
- Een character vertegenwoordigt de eigenlijke speler.
- Een character heeft een CapsuleComponent als basis. Het CapsuleComponent bepaalt de Collision. Binnen het CapsuleComponent bevindt zich de Mesh van het karakter.
- Een character heeft ook een CameraBoom (vergelijk het met een soort selfiestick) waar een FollowCamera aan hangt. Let op, deze zijn niet standaard toegevoegd wanneer uzelf een nieuwe character-klasse aanmaakt.
- Een character heeft CharacterMovement waardoor hij kan wandelen, lopen, zwemmen, springen,…
- Een character bevat basiscode voor netwerken en invoer.
Laten we een character eens van naderbij bekijken.
We hebben een ThirdPerson-project opgestart dus we hebben een ThirdPersonCharacter ter beschikking.
- Selecteer ons ThirdPersonCharacter.
- Bekijk het Details-panel en merk de verschillende componenten op: CapsuleComponent, Mesh, CameraBoom en FollowCamera op.
- Merk ook de overerving (inheritance) van CharacterMovement op.
- Vind in het Details-panel de specifieke eigenschappen voor CharacterMovement.
- Open de ThirdPersonCharacter Blueprint (door bv. op Edit Blueprint – Open Blueprint Editor te klikken).
- Open het tabblad Viewport.
- Hier ziet u de Character-componenten in beeld. U ziet deze ook staan in het Components-panel (normaal linksboven).
Merk ook de ArrowComponent op, deze bepaalt de richting waarin het karakter kijkt (die blauw pijl die vanuit een gevoelige plek vertrekt).
Door de Camera te verplaatsen verandert u de 3D-view op de Mesh.
- Selecteer Mesh.
- In het Details-panel ziet u de gebruikte Mesh (SK_Mannequin) voor uw character en de gebruikte materialen. U kunt deze uiteraard wijzigen (zie later).
- Klik op het tabblad Event Graph.
Hier ziet u de programmeercode die de invoer regelt. Deze is niet standaard aanwezig wanneer uzelf een nieuwe Character-klasse aanmaakt.
U ziet dat een character heel wat toevoegt aan een gewone pawn (moest u een nieuw pawn-klasse aanmaken dan zal u merken dat deze “leeg” is en de hierboven besproken componenten en invoercode niet bevat).
Een nieuwe Pawn, PlayerController of Character klasse aanmaken
Er zijn verschillende manieren om een nieuwe klasse aan te maken.
- In de Content Browser, klik op Add New – Blueprint Class (of klik met de rechtermuisknop in de net aangemaakte folder en klik op Blueprint Class).
- Of, klik in het menu op Blueprints – New Empty Blueprint Class….
U komt in onderstaand scherm waar u een Parent Class kunt selecteren. Bovenaan vindt u de meest gebruikte Parent Classes, onderaan kunt u eventueel een specifieke klasse zoeken (nadien verschijnt een knop Select om deze specifieke klasse als Parent Class te selecteren).
- Klik op de gewenste basisklasse Pawn, Chracter of PlayerController.
- Geef de klasse een naam.
- Maak voor elk Pawn, Character en PlayerController een nieuwe klasse aan, kijk eens rond welke componenten er standaard toegevoegd zijn en geef wat extra aandacht aan het Details-panel. De icoontjes die gebruikt worden verraden al meteen een beetje de inhoud en het doel.
Pawn
PlayerController
Character
Merk op dat de Construction Script en de Event Graph telkens leeg zijn, het is aan ons om de juiste scripting (programmeercode) toe te voegen.
Pawn, PlayerController en Character van de speler opvragen via Blueprint Visual Scripting
U wilt, via programmeercode (Blueprint Visual Scripting) toegang krijgen tot informatie of functionaliteiten van de speler zijn Pawn, PlayerController of een Character.
- In de Blueprint, klik met de rechtermuisknop op de achtergrond en zoek naar Get Player.
Hieronder ziet u de zoekresultaten en is er reeds een Get Player Paw, Get Player Controller, Get Player Character toegevoegd. Deze werken alle drie gelijkaardig.
De Player Index is 0 als er maar 1 speler is. Maar in een multiplayeromgeving moet u aangeven om welke player het gaat op basis van zijn index in het spel.
U weet dat Character meer informatie bevat (CharacterMovement) dan Pawn, hebt u dus specifiek CharacterMovement-informatie of functionaliteiten nodig dan kiest u Get Player Character.
Voorbeeld: stel de vliegsnelheid in van een Character
Vliegsnelheid is CharacterMovement.
- Zoek dus eerst naar Get Player Character.
- Vanuit de Return Value-pin trekt u een nieuwe verbindingslijn en zoek u naar CharacterMovement.
Moest u vertrekken vanuit Get Player Pawn en dan zoeken naar CharacterMovement dan zal u geen resultaten krijgen (tenzij u Context Sensitive zou uitvinken, maar dit kan tot fouten leiden en raad ik dus niet aan). Pawn heeft immers geen CharacterMovement.
Dus vertrekkende vanuit Get Player Character krijgen we onderstaande verbinding:
- Vertrek nu vanuit Character Movement en zoek naar fly.
- We wensen de maximale vliegsnelheid in te stellen (SET), dus kies voor Set Max Fly Speed.
- Vul bij Max Fly Speed vervolgens de gewenste waarde in.
Merk op dat in dit voorbeeld de Exec-pin niet verbonden is en ons programma dus niet weet wanneer deze code moet worden uitgevoerd (en ze bijgevolg ook niet kan en zal uitvoeren).
GameMode, GameState en Game Instance
Informatie over het programma, het spel, zelf worden behandeld door de GameMode en GameState.
Informatie die u wenst door te geven tussen verschillende levels in het project worden, in variabelen, opgeslagen in de Game Instance.
GameMode
De GameMode bevat informatie over de gebruikte klassen.
De GameMode bevat ook de regels van het spel. Denk aan:
- het maximum aantal spelers
- De locatie waar de speler spawt.
- Kan het spel gepauzeerd worden en hoe?
- …
De GameMode is een klasse. Voor ons ThirdPerson-project vindt u deze in de Content Browser in de folder ThirdPersonBP – Blueprints.
- Ga naar deze folder.
- Dubbelklik ThirdPersonGameMode om deze te openen.
- In het Details-panel onder Classes ziet u alle klassen die gebruikt worden.
Hebt u het altijd al vervelend gevonden dat u moest tikken/klikken voor u het spel begon, wel vink dan hier Start with Tick Enabled uit.
U kunt o.a. de GameMode gebruiken om een HUD te koppelen. In deze handleiding hebben we reeds een HUD aangemaakt, we gaan deze nu koppelen via de GameMode.
Merk op dat de gebruikte klasse voor de HUD de standaard HUD is.
- Wijzig deze HUD-klasse naar onze eigen HUD (hier TestHUD).
- Compile en Save.
- Start het programma en merk op dat …
Onze naam staat bovenaan, de gezondheid wordt in onderstaande schermafdruk niet weergegeven!
Hoe weet ons programma nu dat hij deze GameMode moet gebruiken?
U vindt de GameMode op Project-niveau onder Project Settings.
- In het menu Edit klik op Project Settings….
- Klik op Maps & Modes.
U ziet dat de gebruikte GameMode de ThirdPersonGameMode is. U ziet ook de gebruikte klassen die u ook zag in de klasse ThirdPersonGameMode. Eventueel had ik ook hier de gebruikte klassen kunnen wijzigen op het niveau van het project.
U kunt ook de GameMode wijzigen op Level-niveau. De gekozen GameMode voor een Level overschrijft dan de gebruikte GameMode op Project-niveau.
U vindt deze bij de World Settings.
In bovenstaand voorbeeld ziet u dat de GameMode op None staat, dit betekent dat de GameMode van het project wordt gebruikt.
GameState
GameState bevat informatie over de status van het spel:
- Is het spel begonnen?
- Hoelang loopt het spel al?
- …
Game Instance
Game Instance is een manier om gegevens, via variabelen, over te brengen naar een andere level. Het vervult een beetje de functie van een Ini-bestand of Config-file. Namelijk het bijhouden van gegevens, via variabelen, tussen verschillende levels.
U vindt de Game Instance op Project-niveau onder Project Settings.
- In het menu Edit klik op Project Settings….
- Klik op Maps & Modes.
- Onderaan ziet u de Game Instance Class staan.
Klik op het +-teken achter Game Instance Class om een eigen nieuwe klasse te maken.
Game Instance bestaat alleen op project-niveau! Er is dus maar één Game Instance per project.
GameMode, GameState en Game Instance opvragen via Blueprint Visual Scripting
Gebruik Get Game Mode, Get Game State en Get Game instance om de GameMode, GameState en de Game Instance op te vragen.
Casting
Nadien voert u een omzetting (Casting) uit naar de door u gebruikte klasse. Onderstaand voorbeeld Cast de Game Mode naar de ThirdPersonGameMode via Cast to ThirdPersonGameMode.
Voorbeeld GameMode
Onderstaande code vraagt de ThirdPersonGameMode op.
Vertrek vanuit Get Game Mode. We willen echter niet zomaar een GameMode, nee, we willen specifiek de ThirdPersonGameMode. We moeten dus een zogenaamde casting uitvoeren.
- Trek hiertoe een verbindingslijn vanuit Get Game Mode en zoek naar Cast to ThirdPersonGameMode.
- Klik op Cast to ThirdPersonGameMode
Als Third Person Game Mode kunnen we nu verder om bv. de HUD op te vragen (GET) of in te stellen (SET).
Uiteraard moeten we bovenstaand voorbeeld, via de Exec-pin verbinden om het aan de praat te krijgen.
Voorbeeld GameState
Onderstaande code is aan de Tick-event van de Level Blueprint toegevoegd.
Iedere Tick wordt de GameState opgevraagd via Get Game State en wordt via de functie Get Game Time Since Creation de tijd opgevraagd hoelang het spel al loopt. Deze wordt nadien eenvoudig uitgeprint op het scherm.
Onderstaande video gebruikt de Game Instance om de speler van het ene level naar het andere te transporteren.
Project Twin Stick Shooter – Framework Review
De video’s vindt u op Twin Stick Shooter with Blueprint (unrealengine.com).
Bekijk de video:
- Framework Review
Masterclass – Blueprint Game Framework Basics
Onderstaande video toont hoe u het Game Framework kunt gebruiken om muntjes te verzamelen in een level, naar een ander level over gaan en opnieuw nieuwe muntjes verzamelen, alsook de nieuwe muntjes die verzamelt zijn in het nieuwe level toevoegen aan de reeds verzamelde muntjes van de vorige levels.
Ook wordt getoond hoe u gegevens kunt bewaren (iets waar we later op terugkomen).