Getting Started With Unreal Engine 5 For Developers, Part 1: Building Blocks
Everything you need to know to get started in UE5.
In a world where it’s increasingly difficult to make a game, more studios are looking towards premade engines to get a head start. As Unity shoots itself in the foot repeatedly, Epic Games is going from strength to strength with Unreal Engine 5. If you’ve looked for a games job recently, you’ve probably seen more positions listing UE5 experience than at any time in the past.
Most of you have probably tried to follow an Unreal tutorial before and never really quite understood what was happening.
The issue with Unreal tutorials is that in order to learn to be functional quickly for the reward, they give you a hammer. After that, every problem looks like a nail. In reality, there’s an entire toolbox that’s equally accessible, but unless they know what else is in there, people keep reaching for the hammer.
This is not a tutorial. It is a guided reference. It’s not intended to be memorized, it’s intended to be read at a high level, and referred back to as you need it.
What follows is a structured walk-through of what the tutorials don’t tell you about the things they get you to do, so that when you do follow a tutorial or try to build something, you understand the correct techniques to use, and where to use them.
In this part, we discuss the building blocks and how to use them.
In the next article, we’ll talk about how they all fit together in a game and go over common techniques and strategies for how to perform common tasks.
If I get enough questions about the first two parts, I’ll do a FAQ.
This method of learning UE5 works. I’ve brought developers up to speed and functional on various titles using this technique. We’re only dealing with Blueprint here. A lot of C++ exists underneath the Blueprint, but it’s beyond the scope of this primer.
I’m going to be using screenshots and examples from an old prototype of mine called THREADS, which looks suspiciously like single-player cyberpunk League of Legends.
The Basics
Actors and Components
The basic building blocks in Unreal are Actors, and Components.
Actors are the main building blocks of your game. They exist in the game world somewhere - they have a Transform
(location + rotation) in 3D space. Your player character, your NPCs, trees, even the ground itself, are all types of Actors.
This is an Actor
(BP_Enemy
).
Components are things that attach to Actors to provide specific functionality. When you add a component to an Actor in the Editor, it becomes attached, and follows the Actor
around. These are some of the components attached to BP_Enemy
.
Where to start building
If you’ve ever programmed anything, you know that you don’t want to write the same code twice. You want to write it once, then call that code when you need it, like with functions. The first thing you need to decide is where you want that code to live. Let’s start with something simple you’ve seen before. THREADS has combat, so I need to a place to store HP information, and to display a health bar. This needs to happen for the player, for enemies, and for destructible objects. I don’t want to write this code on the player, and every enemy. Instead, I make a Component
for Health.
The Health_Component
Anything in THREADS that takes damage has a Health Component. It serves four purposes:
Stores the max HP and current HP
Displays a health bar, colored for team
Receives notification of taking damage (or healing) from the
Actor
it’s attached toNotifies the Actor when it is out of health, so it knows to die
By putting this functionality in a Component
, I can add the concept of Health and all the associated functions to support it to any Actor
in the game. I just need to put code on the Actor
to tell the Health Component
when damage was taken, and code to program what happens when it dies. Even if different Actor
s have different ways of receiving damage and do different things when they die, the health itself remains managed in the component.
But I also don’t want to have to write code over and over on every Actor
to take damage, send it to the Health Component
, and receive Death notifications. So what should I do? This is where Inheritance comes in.
Inheritance
Let’s say I want to create Enemies in the game. If I used an entirely separate Actor
every time, I’d have to program the same interactions over and over. To avoid that, Unreal makes use of a common programming technique called Inheritance.
Inheritance lets you add a new type of Actor
as a child of a different type, called the Parent. Child classes have all the variables and code of their parent, but let you either extend the class by adding new variables and code, or override it by changing the implementation of the same code.
So, rather than building entirely new class for every enemy, I create a basic, generic enemy class called BP_Enemy
and put a Health_Component
on it. Unreal has a native concept of Damage, so the base class has an event “AnyDamage
” that fires when it takes damage. So, when any damage occurs, we notify the Health Component
, and play Damage Animation.
Events are functions that are triggered when a particular thing happens. They’re a safe way to inform other objects that something happened, and let them take action on it if they want.
In Blueprint, the White wires represent the flow of execution between nodes (functions), and the colored wires pass variables between nodes. Pins on the left of a node are inputs, and on the right are outputs. Drag variable connections between an input and an output to pass them.
Then, when I want to create a specific type of enemy - let’s say an Orc. BP_Enemy
is a child class of Actor, so I’ll make a new child class of BP_Enemy
called BP_Enemy_Orc
. The resulting class has all the functions and variables for an Actor, plus the ones I added in BP_Enemy
, plus any new ones I add for directly to the Orc. I can change also specific properties/variables that were set on BP_Enemy
, like a new Max HP value on the component, replace the Actor
’s Mesh with a new Orc model, and replace the Damage animation with one designed for Orcs. I repeat this process for every new kind of Enemy, just changing the parameters I need to be different, but with all the base variables and functions intact.
Now we have a base class of Enemy that we can build different types of Enemy from, and a Health Component
we can put on anything that needs HP.
Key takeaway:
To put different behaviors/data in objects that are similar, use child classes. E.g. I want to make ten different kinds of Enemy.
To put the same behavior in objects that are different, use components.
E.g. I want to add Health to Enemies, Players, and Obstacles.
Almost everything in Unreal inherits from something else. All actors inherit from AActor. All objects (including Actors) inherit from UObject. Almost everything you make in Unreal will inherit from some other class.
Even components can be children of another component class. They inherit from UActorComponent, and can be extended and overridden the same way.
Inheritance is also how Unreal’s C++ works to provide Blueprint classes. You can make classes in C++ and then make a child class from it in Blueprint to get it in the Editor.
Final note on adding how Actors and Components work: Every variable or function can be public or private, which determines whether it can be accessed from inside your Blueprint, or whether other Blueprints can access it. If you add a variable to your Actor or Component but can’t access it elsewhere in the code, check its visibility.
How Stuff Works
We started with Actors
and Components because they’re the basic building blocks. Next, you need to actually write code in them.
Places You Can Write Code
There are four main ways that code executes in Unreal: Functions, Events, Timers, and Tick. We’ll approach them in that order.
Functions
Functions are a way to group a chunk of reusable code together that can be called on demand rather than rewriting it every place you need it. Functions can have inputs (arguments) and outputs (return values), but they don’t have to have either.
Here’s a function in THREADS with one argument, and no return value. It gets called when an Actor enters firing range, and the argument is a reference to that Actor called “Target Entering”. It checks if it’s targetable, then checks if it’s currently targeted, and if yes to both, alerts the Player Controller that it’s fine to start attacking.
Key takeaway:
Use Functions when you need to execute the same code a number of times inside the same Blueprint.
In Blueprint, functions are guaranteed to return on the same frame. This means you can’t use Delay
nodes in them, because it would delay the entire current frame. So what do you do when you need to run code, but don’t need to wait for it to finish?
Events
Events (also called Delegates) are asynchronous - fire and forget functions that won’t blow things up if the listening object goes away.
When you want to trigger actions on one or more objects in response to something happening, you probably want Events. All Unreal Actors
have a tonne of Events built in from AActor
. One that you’ll see frequently is “Begin Play
”. It’s fired when an actor finishes spawning in the level. Here’s one for an enemy Actor
. When it triggers, it sets the enemy’s team to Hostile, creates a health bar, and adds it to the enemy Actor
.
Here’s another common pair: “On [Actor/Component] Begin Overlap”, which basically means “something else touched me”, and then On End Overlap for the opposite (that thing is no longer touching me). They’re generally used to trigger interactions between different Actors. Events can have arguments passed to them like functions - in this case, BeginPlay has no arguments, but when Overlap fires, it’ll pass in information about the overlap itself.
These are Overlap Events from a Collision Sphere
called “Interact Radius” on the Player Character
. Collision volumes exist to identify when things collide, and"Begin Overlap” fires when something overlaps with it. When that happens, it calls the function “On Enter Interact Range” which enables interaction with another object in the game.
Key Takeaway:
Use Events when you need to trigger code, but don’t need to wait for it to finish.
You can also trigger Events asynchronously on a delay using..
Timers
Timers do stuff after a delay. They return an object called a Timer Handle that holds information about the timer, like how much time is left. You can also do things like terminate early and do the stuff, or just kill it and do nothing.
Here’s an example of using Timers to make a weapon reload. The “Start Reload” event:
Sets “Attack Available” variable to false, locking you out of shooting.
Starts a timer with length Reload Time. The event pin for the timer connects to the “Finish Reload” event.
When the timer expires, the “Finish Reload” event fires.
Sets current ammunition amount to the max size of the magazine
Then finally, re-enables Attack Available.
Tick
Events: “A thing happened, let’s do stuff”. But what about things you want to be constantly updated? You use Tick.
Every Actor
and Component
has a Tick()
function that, if enabled, runs every frame (sort of). Use it for anything you need to be calculated or updated every frame.
The Unreal Top Down Example project’s Tick()
function to get the mouse cursor’s position, raycast down into the world, and render a decal on the ground underneath it.
In THREADS, there’s a particular component that I want to always be facing the camera. The tick code runs every frame to rotate it with Set World Rotation()
.
You can also set the tick time to be slower, on an interval. If it’s not important that it happens immediately but is important that it happens constantly, you can set an Actor’s tick to happen at longer delays. If I have a system that’s constantly changing the time of day and adjusting the sun position and lighting, it might need to only run every five seconds, so I’d set the tick time to 5.
Tick is great, because it means things can be always updating themselves. However, Tick can also be bad, because again, the code will run every frame. Executing unnecessary or expensive code on Tick every frame is the fastest way to slow your game down. There’s a function “Get All Actors” which just … lists every actor in the game. There’s actually a warning on it that says “DO NOT CALL THIS ON TICK”. Yes, it’s in capital letters.
Key Takeaway:
Use the On Tick function for things that must update constantly.
All Actors and Components can Tick.
You can tick at a larger interval instead of every frame.
Also you can disable or enable Tick for any Actor or Component as needed.
A Component cannot tick if the Actor it is attached to has Tick disabled.
More info in the docs on Actor Ticking.
So now we’ve got four methods of executing code. Where do we put that code?
Tools
Pawns and Controllers
A Pawn is an Actor
that’s controlled by a Controller to make it do things. The Controller allows your game to issue commands to Actors, like “Move in this direction” or “Stop” or “Walk to this location”.
A Controller
can take commands directly from code, but there are also two special kinds of controllers: Player Controllers and AI Controllers. They’re both children of the Controller class, and extend it in different ways.
A Player Controller
receives inputs from the player (key presses, mouse, etc) and translates them into specific directions it can pass to the Pawn. It’s preconfigured with the inputs you configured for your project like mouse, gamepad buttons, or key presses.
An AI Controller
has a bunch of tools on it for making AI for NPCs, like Behavior Trees, that let you program rules for how the Pawn should behave.
Pawns
don’t do a whole lot on their own. The code on the base Pawn
class is mostly about taking commands. If you want an actual NPC in your game, there’s a child class called Character that has all the stuff you probably want.
A
Mesh
, so it has a 3D model to display and animate.A
Movement Component
that controls walking, running, falling, etc.A
Capsule Component
for collision.A bunch of networking / multiplayer code.
That’s everything you need for an NPC, but a player-controlled character is going to need more. There’s a Player Character class that adds things like:
Input from a
Player Controller
A
Camera Manager
for controlling the viewportA UI / HUD Overlay
Force Feedback effects
Key takeaway:
A Pawn is an Actor controlled by a Controller
AI Controllers control Characters
Player Controllers control Player Characters
Create child classes of Character for NPCs
Create child classes of Player Character for players
Create a child class of Player Controller to customize input handling
When a Controller
takes control of a Pawn
, this is called “possessing” it, which is definitely not creepy at all.
For more info, check out docs for Player Controller and Pawn.
If you want more info on how input is handled in UE5, try Enhanced Input.
Collision & Traces
Collision is a means of checking if an Actor
touched another Actor
. There are two types of collisions available: Hits (blocking) and Overlaps (non-blocking).
An Actor
has a collision Object Type - other types of Actors
then configure how they should respond to collisions for that object type, and whether they should ignore them, fire an Overlap event, or block (collide) and generate a Hit event.
Use Collision to configure what kinds of
Actors
should pass through each other unnoticed, what should overlap, and what should stop. You might use Collision object types to let friendly fire pass through teammates, but hit enemies.
You can also do Traces, to check what something might run into. You can trace in a line, or in a shape, like a box. Traces occur on Collision Channels and instruct Actors
on how they should respond to a particular type of trace.
Use Traces to measure what you might hit in a particular direction. You might use Traces to tell if there are interactable objects in your field of vision.
Collision is what triggers Events
like the one I’m going to reference next, for one Actor
overlapping another.
But when you test Collision, the function returns an Actor
reference. You don’t know what the collided object is yet, so how do you find out, and do stuff relevant to it?
Casting
The answer is Casting. This one’s a bit complicated, and deals with Inheritance again.
In THREADS, items that can be picked up inherit from a base Pickup class, which inherits from Actor
. An Ammo pack’s inheritance goes:
Actor
→ BP_Pickup_Base
→ BP_Pickup_Ammo
In the below code, I have an event that fires when any Actor
enters an automatic pickup radius around the player. We want to pick up anything we have inventory space for, and show a warning instead if it’s full.
But you need to declare types of variables on functions and events, and the overlap function needs to return any Actor
, so its output type is set to Actor
.
We can pick up anything that inherits from BP_Pickup_Base
, and the Actor
we overlapped might be, but there are two problems:
We don’t know if it IS a child of
BP_Pickup_Base
.Even if it is, we can only access the properties of the
Actor
class, because that’s the Type we were given for this object reference. We can’t access the variable for how many inventory slots it takes up because we’re looking at it through a base Type lens.
Casting lets us solve both these problems at once by trying to treat the object as a different type.
An object reference’s class (type) is what lets Unreal know what variables and functions exist on an object, and where to find them. Our child class BP_Pickup_Base
has an Inventory Slot Cost variable, but since the reference is currently of type Actor
, we can’t see it. So we attempt to Cast our Actor
to BP_Pickup_Base
.
If it works, then it is a BP_Pickup_Base
or a child of it, and then we can access the variables stored on BP_Pickup_Base
, including the one we need: “Inventory Slot Cost”.
Since we now know that it is a pickup, we can retrieve the inventory slot cost and we can tell if we have enough inventory space for it and figure out whether to pick it up or just show a warning that inventory is full.
The object always was a BP_Pickup_Ammo
- it was just originally referred to as an Actor
, and then cast to BP_Pickup_Base
. You could cast it to BP_Pickup_Ammo
, or back to Actor
, and it would work. The object itself remains unchanged, but the variables you could access would be different, because the type instructs how to access them.
Internally, the Event
is triggered by the BP_Pickup_Ammo
object, but casts it to Actor
before it fires since you need to declare the argument type when you create an event. If it didn’t, you’d need a separate event for every different child class of Actor
you might overlap.
It’s kind of like a template for a business listing on Google. If a business is a restaurant, and Google has menu data for it, it will display that on the profile. But if the template for the profile is set to a generic business listing, even if Google has the menu data, there’s nowhere in the UI for it to display.
You will primarily use casting in two situations, both because generic functions/events tend to return base class type references.
An overlap or collision event returns an
Actor
reference, which we may want to do something with, so we cast it to a type to do something.A generic function like
Get Player Controller
returns the base Unreal player controller class, but if we’ve extended it to our ownPlayer Controller
class and are using it, we need to cast the returned player controller to our class to get access to the extra stuff on it. In the function we saw earlier, I get the player controller and Cast it to our actual player controller classTopDownController
.
You can cast an object to any type in its inheritance chain. Don’t worry, this is as Programmer as it gets, and there’s more info in the Cast documentation.
But what if you want to call the same function on two objects that don’t have a shared parent? There’s a tool for that called..
Interfaces
We talked about when you want similar objects to have different behaviors, and when you want different objects to have the same behaviors, but what if you want different things to react differently to the same interaction?
That’s what Interfaces
are for. An interface is a virtual set of functions that you can apply to any object that give other objects a defined way to interact with them.
In THREADS, “Interact” does different things depending on what the object is. If it’s a person, it’ll start a conversation. If it’s an item, it will pick it up. To achieve this, we create an “Interact” interface, and define functions on it for Interaction Start
and Interaction End
, then add that interface to my Pickup
base class and my NPC
base class.
On the Pickup base class, I implement the Start Interaction function from the Interact interface, and write code to call the inventory pickup logic, and updates any quests that are listening that have a ‘pick up this thing’ task.
On the NPC base class, I implement the Interaction Start
function from the Interact
interface, and write code to trigger the UI for dialogue. I also implement the Interaction End
event because I need to undo stuff if the player terminates the conversation early, like reset the camera position (Set View Target).
Finally, when an object enters the interaction radius of the Player Character, instead of checking its type, I can simply check if it implements the Interact interface, and if it does, (after some other checks) call the Interaction Start
function.
With that final method of calling code out of the way, we can get back to types of Actors
.
Volumes
Volumes are three-dimensional Actors
(usually boxes) used to alter the behavior of areas within levels.
Unreal includes a bunch of different types that do different things:
Triggering
Events
when you walk into them.Blocking
Actors
from walking into them.Changing the way a level calculates its lighting or visibility.
Use Volumes
any time you care whether or not any Actor
is inside of any particular space in your game.
For more information on the kinds of Volumes
available out of the box, check out the official documentation.
Brushes
The geometry of a Volume
comes from its parent class Brush
. Brushes are an easy way to quickly make test level geometry. They can be Additive or Subtractive, meaning they either get used to place geometry, or act as a cutout for it. I’m going to show you where to find them because it’s hard to find.
This is an example of two box brushes. One is set to “Additive” to make the box itself and set to Hollow so it’s just the walls. The other “Subtractive” to cut a hole out of it, which is highlighted.
These aren’t to be used in your final game. You’ll need to convert them to…
Meshes
If your Actor needs a 3D model, add a Mesh Component
.
Meshes are 3D models. There are two kinds of Mesh: Static Mesh
and Skeletal Mesh
. Static Meshes don’t move or animate, but Skeletal Meshes have a “skeleton” (rig) that controls how they move and animate. If an Actor
has a 3D model in the game, it probably has a Static Mesh
or Skeletal Mesh
.
Animation
The animation rig in a Skeletal Mesh
lets parts of it move. A particular unique animation for a rig is called a Montage. The overall animation of a Skeletal Mesh
is controlled by an Animation Blueprint, which is a tool for telling what animations should play under what conditions, control the transitions between them, and how they can be blended together. In technical terms, you can think of it like a State Machine. It represents the state of your character (walking, running, standing, falling), defines animations for each state, and configures how to transition between other states.
Animation Blueprints
allow you to blend animations together - for example, you might have one animation for Walk and one for Run. As you speed up, they will slowly mix together to create a smooth transition. This is called a Blend Space.
You can also layer animations together - like playing a cheering animation with the upper body while still running. Look up Additive vs Full Body for more info.
Widgets / UI
UI in Unreal is basically made up of Widgets, which are objects that render a 2D image of some sort. They’re commonly used for menus, buttons, and overlays.
Widget editing has two pages, which you swap between in the top right: Designer, and Graph. The Designer page is where you create the layout, the Graph page is where you add your code, like a regular Blueprint.
You can add them to the viewport to become part of the UI.
To use a Widget, first Create it, then either add it to the viewport (screen), or assign it to a Widget Component
on an Actor.
If you want to make a popup menu or clickable UI, you’ll need to give focus to the keyboard, and set input mode to UI only.
When destroying your menu, don’t forget to bring back input mode and unpause:
You can also add Widgets to Actors using a Widget Component
. This is good for character nameplates or health bars. Widgets attached to Actors can exist in “Screen Space” (2D, drawn over the top) or “World Space” (3D, part of the game world).
If you want to do Screen Space widgets, you may need to do line traces to the camera occasionally, to check if they should be seen, otherwise far away characters will draw over the top of the rest of your game.
The alternative that I use in THREADS is that they’re in World Space, so they can be occluded by the environment. I use the Tick function to manually face them towards the camera by getting the camera rotation, then flipping it 180 degrees.
For more info, check out the Building UI page.
Sound
Unreal actually has a pretty complicated sound system out of the box, and the documentation is incomplete. Don’t feel bad if you’re struggling. There’s a short guide to importing .wav files into your game here.
Once you have a sound in, you’re probably going to want to use it for one of four things:
2D sounds like menu clicks
3D sounds that occur in the game world
Dialogue (can have subtitles attached)
Ambient sounds, that play when you’re in a space
It’s difficult to find documentation on Unreal sound, so here’s a list of all the Blueprint nodes you can use related to sounds.
You can play sounds either using Gameplay Statics
that are unrelated to any Actors
, or you can add an Audio Component
to an Actor
and have sound “emit” from it.
The best way to learn sound is to just try it, and it’s the one of two things in this primer that I’m going to tell you to just get in editor and mess with the functions listed above, and see what happens.
Key Takeaway:
Sound is hard but there’s probably an engine function for your use case
VFX
The other thing you should just get in and play with is VFX, which is done through Niagara. The Niagara documentation is similarly incomprehensible if you don’t already understand it, so we’re going to simplify it down to “how to use what it ships with”.
Niagara displays VFX in the game world, like smoke, particles, or fluids - things that would be too complex and expensive to simulate in regular actors.
Niagara works in two parts: Systems, and Emitters.
A System is a controlling actor - it doesn’t actually do anything on its own. It exists to control Emitters, which are the things that actually make the particles you’re simulating. A system can have multiple emitters - the Fire systems below might have one Emitter for the fire effects, and another Emitter for the smoke.
Most premade assets will be a System with Emitters preconfigured on it, and the controls available on the System generally set things like how long the particles hang around for and how far they travel. If you want use one of these Fire systems, and you want more fire and less smoke, you’d likely configure that on the System itself rather than going in and editing the Emitter directly.
To get started, first you have to enable the Niagara plugin, then add a System to your level or actor. There are premade systems you can use like the Fire ones above, or you can download more. The details of Niagara are too complex to cover here, but you can learn more by editing existing Systems to see how they work.
Key Takeaway:
Niagara Systems are controllers for Emitters.
Emitters are the things that actually make the particles / fluids / etc.
Particles don’t entirely exist in the game world because this is GPU magic.
Data
The last piece of the puzzle is data itself - how variables are stored. Data in Unreal functions similarly to most other programming languages, and there is no way around how Programmer-ey this is.
You may find yourself glazing over during this last section, as it’s almost purely technical. Don’t worry, we’re nearly done. This is mostly a reference so you can look up the details if you need them.
Variable types
Variables are ways to store data, like references to actors, or integers (whole numbers), but they can be organized in different kinds of containers.
Properties, which are just actual stored variables on an object.
References, which link to a stored variable somewhere else. Functions in Unreal pass objects with by value (copies the whole object) or reference (link to the original). Most variables in Unreal are passed by reference. Changing a copy doesn’t affect the original. Changing a referenced object does.
Arrays, which are a list of a particular type of variable you can iterate over or access certain slots in. The items in the list have an explicit order.
Maps, which uses a key of one variable type to store or retrieve another. They are unordered and fast. If you have a very large array you need to find one particular value in, you might want a
Map
so you can look it up directly.Class references, which treats the class type AS a variable. Useful for storing what type of object to spawn.
We mostly care about Arrays, because they’re the most common in the engine.
Many built-in functions that need to return multiple results like “Get All Overlapping Actors” will return an Array
. Your inventory might just be an Array
of items. They are ordered, and can also be sorted. Searching an Array
requires inspecting every value manually, so it can be slow for large numbers of entries if you don’t know which entry you need.
Individual items in an Array
are accessed by “index”, which is basically just a count of ‘how many items along are they’. The first item is 0, second is 1, etc. Adding or deleting items from an Array
will cause other array items to change their index. If you loop over an Array
containing fruit, and in each loop, delete the current item, this will happen.
Tip: If you’re iterating over an array of items and you plan to remove any of them, iterate over it backwards - from last item to first, using a Reverse ForEach loop. If we had walked the array from the end, rather than the start, this would not have happened, as removal would not cause indexes to shift.
Maps work on keys, so they don’t have this problem. When you add an item to a Map
, you provide a specific Key
to retrieve it, and set the Value
for that key to your data. Here’s the same operations from before, but performed on a Map
.
This may sound like an argument to use Maps
all the time instead of Arrays
, but Arrays
are ordered - you can shuffle the elements around, and the order can mean something, like which slot in an Inventory something is in. Maps
are unordered, but they’re good for looking up one specific thing.
You might use a Map
to keep track of every line of dialogue in the game, by having the Key
be its line ID, and the Value be the text itself. You couldn’t do this with an Array
, because if you were storing which line was associated with which index, every time you delete a line, you’d renumber the rest of them. Neither is better or worse than the other, they’re just used for different things.
Here’s an article on how to use Arrays in more detail.
Structs and Enums
Structs are a way of grouping a number of variables that are commonly used together into a single object, so they can be passed together. They’re like classes, but with less functionality.
A common example of a struct: When you Trace for collision, you don’t just want info about what you hit, but also other info like the location of the collision, and whether it was a block or an overlap. It would be bothersome to have separate variables for every possible bit of information you might need separately, so all Traces returns a single HitResult
struct containing all the variables you need. Then, it’s easy to pass that data around as a single unit relating to that “hit”.
To access the individual variables inside a Struct, you “Break” it to expand them out and get one pin each. To create a Struct, you “Make” it, which takes all the variables individually and outputs them as a single struct variable.
Enums are a particular variable with a number of preset options. They’re good for making dropdowns, or handling the same object differently depending on which of the preset values it has. Use them for Types of other things.
Here’s an example: I have a Data Table
(like a spreadsheet), and when I request a row from it, I get a Struct containing a variable for each column.
In this screenshot, each row in the DT_Pickupable
table contains a single Pickupable Struct
with all the information about a pickup. I retrieve a single Pickupable Struct
from a table, and “break” it to access the variables - specifically the Pickup_Type Enum.
I use a Switch node to reroute the code depending on what the value of the Pickup Type Enum
is, to execute different code for each pickup type.
That’s The End Of Part 1
These are all the basic moving parts of Unreal Engine 5 that you’ll need to make a prototype of something. If you’ve followed any tutorial, you’ve probably been asked to use some or most of these, but not understood what they did or why. I hope this clears it up. There’s a lot more - this is just the basics.
Stay tuned for Part 2, where we’ll take all the elements we just learned about, learn how they fit together in the game, and teach you how to apply these tools to solve common problems.
// for those we have lost
// for those we can yet save