© David Nixon 2020David NixonBeginning Unreal Game Developmenthttps://doi.org/10.1007/978-1-4842-5639-8_5
West Palm Beach, FL, USA
In this chapter, you will learn about Blueprints, a visual scripting system used to script logic in Unreal. You will learn about Level Blueprints, Blueprint Classes, variables, arrays, functions, flow control, Timelines, how to debug Blueprints, and more.
Introduction to Blueprints
In the Unreal Engine, a Blueprint is an asset that contains data and instructions.
So far, this book has mainly shown you how to construct environments that can be used for games. But the environment is only one half of a game. The other half is the logic that determines how the environment can be interacted with and how the game is actually played. This is where Blueprints come into play.
Using Blueprints, you can keep track of health, energy, score, and so on. You can also specify game logic, like the requirements for completing a puzzle, what happens when that puzzle is complete, what happens when you shoot an enemy, and so on.
Level Blueprint vs. Blueprint Classes
There are two main types of Blueprints – the Level Blueprint and Blueprint Classes.
A Level Blueprint is used to hold data and instructions for a particular Level. It might hold data such as the time remaining to complete the Level, or the number of keys you’ve collected in that Level, and so on. It’s also used to store instructions that pertain only to that Level. For example, let’s say there was a spot in a Level where there was a bridge, and when the player crosses that bridge, a meteor flies across the sky. If that’s a one-time unique occurrence just for that spot in that Level, it would make sense to store those instructions in the Level Blueprint for that Level.
Blueprint Classes are a way to turn any Actor or asset into a Blueprint. The Engine comes with several pre-made Blueprint Classes, such as Pawn, Character, Player Controller, Game Mode Base (all of which will be covered in the next chapter), and many more. However, you can also create your own Blueprint Classes. This allows you to create objects with custom traits and behaviors.
Let’s say, again, that you are building a haunted house. And let’s say you want to have a chair that floats up and down. Let’s also say that you want your character to be able to shoot the chair and, eventually, destroy it. You can achieve all of this by creating a Blueprint Class out of the chair Mesh.
Within the Blueprint, you could specify that the chair should move straight up and down, over and over again, starting from wherever it is placed in the Level. You could also specify that it should contain a variable called Health with a default value of 100. You could also say that any time the chair was hit by a projectile, that 10 should be subtracted from its Health. Finally, you could specify that if the Health of the chair ever gets to 0 or below, the chair should be destroyed.
One of the great things about Blueprint Classes is that you can use them to create as many copies, or instances, of your creation as you want. Using the haunted chair as an example, once you completed the Blueprint, it would be available to you in the Content Browser, and then each time you dragged it into the Viewport, it would create a new instance of the chair. Each chair would float up and down, starting from the position they were placed, and each chair would have their own copy of the Health variable. So if you damaged one of the chairs, its Health would be 90, while the other chairs would still have a Health of 100.
Level Blueprint Editor
To open a Level Blueprint, go up to the Toolbar and expand the menu of the Blueprints button. Then click “Open Level Blueprint.” This will open the Level Blueprint Editor.
Inside the Level Blueprint Editor is the Event Graph. The Event Graph is the area of a Blueprint where you script the logic. If you’re a programmer, the logic can be scripted in pure code using C++. However, Epic Games has developed a visual scripting system that allows non-programmers to script logic and can be convenient even for experienced programmers.
The scripting system works by using various Nodes that each serve a specific purpose and connecting those Nodes together. By default, the Level Blueprint starts off with two commonly used Nodes in the Graph, as seen in Figure 5-1. They are disabled to start with, but can be used right away by connecting them to another Node.
The Event BeginPlay Node and Event Tick Node start in the Level Blueprint by default
The first Node is the Event BeginPlay Node. An Event Node is a Node that is activated when a certain event occurs. So an Event BeginPlay Node, inside of a Level Blueprint, will be activated by the event of the Level first starting. You can recognize an Event Node by its top strip which will be the color red and will have an icon of an arrow inside of a diamond symbol.
The second default Node is also an Event Node. The Event Tick Node is a Node that is activated on every tick of gameplay. Before every frame of the game is drawn on the screen, any logic connected to the Event Tick Node will be executed. This is useful in situations where you need to constantly check certain conditions that, when met, will have an immediate effect on the game, such as the main character colliding with something harmful.
Pins and Wires
The icons along the left and/or right sides of Nodes are called pins. Pins on the left side of a Node are input pins, and pins on the right side of a Node are output pins. Pins are used to input/output data to and from Nodes and to specify the order in which Nodes should be executed.
Pins can be connected to one another with wires. To create a wire, left-click a pin and then drag the mouse while still holding the LMB. This will drag a wire out of that pin (Figure 5-2). If you hover over another pin and release the LMB, it will connect the end of the wire to that pin.
Wires can be dragged out of pins
Pins with a white icon that looks like a Play button are execution pins . Execution pins on the left side of a Node are input execution pins. When a wire connected to an input execution pin is activated, it will trigger execution of that Node. Execution pins on the right side of a Node are output execution pins. Wires connected to an output execution pin will activate once that Node has finished executing. Output execution pins can only be connected to input execution pins and vice-versa. By chaining Nodes together through their execution pins, you can define a series of Nodes that should be executed, one after the other, every time the first Node in the series is activated. The first Node in a chain will always be an Event Node.
Pins with a circular icon are data pins. Data pins are used to pass data between Nodes. Output data pins can only be connected to input data pins and vice-versa. Whatever data is contained in the output data pin gets sent to the input data pin it is connected to.
To add a new Node to the Event Graph, you will need to select that Node from the Node Menu (Figure 5-3). The Node Menu can be brought up by right-clicking any empty space in the Graph or by releasing the LMB over any empty space when dragging out a wire from an output execution pin. When doing the latter, the Node you add will automatically be connected to the wire.
You can add Nodes from the Node Menu
There are many Nodes available to choose from in the Node Menu. They are organized into categories, but if you know at least part of the name of the Node you’re looking for, you can use the search box at the top of the Node Menu to search for it.
Before you can test any new logic you have created, you must compile the Blueprint. Compiling just means that the Engine will convert the logic into machine code that the computer can understand. In order to compile the Blueprint, simply go up to the toolbar of the Blueprint Editor and click the Compile button (Figure 5-4). If there is any new logic that hasn’t been compiled yet, the Compile button will contain a question mark icon.
The Compile button
Simple Blueprint Example
Here is a simple, albeit non-practical, example of a Blueprint to help you gain familiarity. Figure 5-5 shows a Level Blueprint whose logic specifies that the game should exit two seconds after the Level begins.
This logic will cause the game to exit two seconds after the Level begins
As mentioned earlier, the Event BeginPlay Node will be executed when the Level first begins. As a consequence, any Nodes connected to the Event BeginPlay Node through execution pins will get executed as well.
The Event BeginPlay Node is connected to a Delay Node. The Delay Node is a Function Node. Function Nodes are light blue and have an icon of a lowercase “f.” A Function Node is a Node that performs a specific task when executed. The task of a Delay Node is to wait for a specified amount of seconds before passing execution on to the next Node. In this example, a value of 2 seconds has been specified. A Delay Node doesn’t delay the execution of all logic in the game, just within the flow of wires it’s connected to.
After a two-second delay, execution will pass to the Quit Game Node which will cause the game to exit.
Variables are what Blueprints use to store data. Just like in algebra, where you might use a variable named X to store a number, you can use variables in Unreal to store data. But in Unreal, variables can hold other kinds of data in addition to numbers, such as text.
To create a variable in Unreal, first look on the left side of the Blueprint Editor for the My Blueprint tab (Figure 5-6). Within the My Blueprint tab is a Variables sub-tab. Clicking the plus sign on that tab will create a new variable which can then be named.
You can add new variables in the My Blueprint tab
A variable’s data type determines what kind of data it can hold. One way of setting the data type is to click the rectangle to the left of the variable’s name, and then choose the data type from the menu that appears. The menu will contain a list of all the basic data types in Unreal, as shown in Figure 5-7. Each data type can be identified by a unique color.
Each data type in Unreal can be identified by a unique color
The first one on the list is the Boolean data type, which is identified by the color red in Unreal. A Boolean data type is simply used to hold a value of True or False, and those are the only two values it can hold. Because of this, a Boolean data type takes up very little space in memory.
The next four data types in the list – Byte, Integer, Integer64, and Float – are all used to hold numbers. But they each hold different kinds of numbers and each take up different amounts of space in memory as a result.
Byte is the smallest of the four , meaning it takes up the least amount of space in memory. This is because a Byte can only store a whole number between 0 and 255, inclusive. So if you needed a variable to store, for example, some choice that the player makes in the game, and there are only a limited amount of choices the player can make, a Byte might be a good data type to use to store this choice, with each number corresponding to one of the choices the player could make.
Like Byte, the Integer data type is used to store whole numbers. But unlike Byte, it can hold numbers between about negative 2 billion and positive 2 billion. Because of this, however, it will also use more memory than a Byte.
Integer64 has a range between about negative 9 quintillion (18 zeroes) and positive 9 quintillion. Again, the trade-off for that extra range is an increase in the memory required.
Float is short for “floating point number.” A “floating point” is just another name for a decimal point. So a Float is used to hold numbers that have a decimal place. Unlike the Integer data type, it can be used to store numbers that aren’t whole, such as 3.5, or 24.743, and so on. Because of this, it requires more memory than an Integer.
The next three data types are used to store text. The largest of the three is the Text data type. Because this requires the most amount of memory of the three, it should only be used for its specific purpose, which is to store data that will be displayed on the screen to the player. The Text data type is useful for displaying text because it has, among other things, localization features, which allows it to display text in a way that is custom for that player’s region or language.
The String data type is used to store text that you can perform manipulation functions on. These functions include extracting a substring of text from the larger portion; changing the case of the text, meaning uppercase or lowercase; reversing the text; and so on. The String type is smaller than the Text type, so if you might have a need to perform these functions on the text, and the text isn’t going to be displayed on the screen, you would store the text in a String variable.
The smallest of these three data types is the Name data type. The Name type doesn’t have the localization or other features that the Text data type has to display text on the screen, and it also doesn’t have the manipulation functions of the String data type. However, it does take up the least amount of memory of the three. So you would use the Name data type for any text that doesn’t require the features of the String or Text data types.
The Vector data type is used to store three Float values. This is useful for defining a point in space, an RGB value, or anything that is defined with three values.
The Rotator data type is used to store numbers that describe an object’s rotation in 3D space.
The Transform data type is used to hold data that describes an object’s position, rotation, and scale in 3D space.
A Get Node is a Node whose only purpose is to output the value of a variable (Figure 5-8). It will contain just a single pin, an output data pin. It has no execution pins. A Get Node can be thought of as always active, because it will output the current value of the variable, every tick of gameplay, to whatever pin it is connected to.
A Get Node for a Float variable named “Delay Duration”
To create a Get Node for a specific variable, left-click the variable in the My Blueprint tab and drag it into the Event Graph. When you release the LMB, click “Get” from the menu that appears. This will create a Get Node. Another way to do this is to hold down the Ctrl key when dragging the variable into the Graph, and then when you let go of the mouse, it will automatically create a Get Node for the variable.
A Set Node is used to change the value of a variable (Figure 5-9). It contains an input data pin which is used to specify what value the variable should be changed to. The value will be changed once the Node is activated through its input execution pin. The Node also contains an output data pin so the new value can be passed on to another Node if you wish.
To create a Set Node for a specific variable, left-click the variable in the My Blueprint tab and drag it into the Event Graph. When you release the LMB, click “Set” from the menu that appears. This will create a Set Node. Another way to do this is to hold down the Alt key when dragging the variable into the Graph, and then when you let go of the mouse, it will automatically create a Set Node for the variable.
A Set Node for a Float variable named “Delay Duration”
A default value is a value that will be assigned to a variable as soon as the variable is created. The default value can be set in the Details Panel, on the right side of the Blueprint Editor, under the “Default Value” category (Figure 5-10). If you see the text “Please compile the blueprint,” it means that you haven’t compiled the Blueprint since that variable was created. Once you compile the Blueprint, that text will go away and a box will appear where you can enter the default value.
When you create a new variable, you will need to compile the Blueprint before you can give that variable a default value
Updated Blueprint Example
Expanding on the Blueprint example from the previous section, Figure 5-11 shows an example of using a variable to specify the duration that the Delay Node should delay.
The Duration property of the Delay Node is now set by a variable
The Set Node sets a Float variable named “Delay Duration” to a value of 5.0. A Get Node for the “Delay Duration” variable passes the value of that variable to the Delay Node. So now, the Delay Node will delay for 5 seconds instead of the 2 seconds that were “hardcoded” into the Node in the previous example.
In addition to the default value, there are other properties of variables that you can set in the Details Panel (Figure 5-12). Some data types will have different properties than others.
Properties of a Boolean variable
The first two properties, Variable Name and Variable Type, are the same properties that you can edit in the My Blueprint tab, so the Details Panel is just another place where you can set them.
The Instance Editable property will be covered in the section on Blueprint Classes.
The Blueprint Read Only property can be used to make the variable read-only, meaning its value can’t be changed; it will always contain its default value. With this checked, if you added a Set Node to the Blueprint for the variable, you would get an error when trying to compile the Blueprint.
The Tooltip property allows you to give a detailed explanation of what the variable is and what it is used for. This is useful not only when you are working on teams – so that the people you are working with can more quickly understand what you’ve created – but also for yourself, so that when you come back to the variable at a later time, you can quickly remember its use.
To create a tooltip, just type the message into the Tooltip box, and when the variable is hovered over in the My Blueprint tab, or when a Set Node for that variable is hovered over, it will display the tooltip message that you’ve created.
The Expose on Spawn and Expose to Cinematics properties involve more advanced topics and won’t be covered in this book.
The Private property determines if other Blueprints can access the variable. With this unchecked, other Blueprints will be able to access the variable. With it checked and set to Private, other Blueprints would not be able to access the variable.
The Category property allows you to group your variables into categories if you wish. This is for organizational purposes within the Editor. To place a variable into a category, select an existing one from the dropdown or create a new one by typing its name into the box. Once a variable has been placed into a category, it will appear under a heading for that category in the My Blueprint tab.
The next two properties are Slider Range and Value Range. These properties are only for numerical data types.
Starting with the Value Range property, this allows you to set a minimum and maximum value that the variable is allowed to contain. If you set the Value Range to 0 to 10, you won’t be able to set the variable to anything other than those numbers and the numbers in between. If you go down to the Default Value, for example, and try to set that to 11, it won’t let you.
The Slider Range property determines what value you can set the variable to when using a slider. If you set the range to 3 to 5, for example, and try to use the slider on the Default Value to set the number, it will only go between 3 and 5. But if you enter a number manually, you can still enter any number not restricted by the Value Range or the limits of the data type itself.
The Replication property is used in multiplayer games that are running over a network. This specifies whether or not the variable should be replicated over the network. So if it’s a variable that would affect all the players in the game, it would need to be replicated over the network. But if it’s a variable that only affects an individual player, it would probably not need to be replicated over the network.
If a variable is set to be replicated, the Replication Condition property can be used to set the conditions under which the variable should be replicated.
An array is a list of variables of the same data type. You can have an array of Integers, an array of Strings, and so on.
This is useful whenever you need to store a group of something. For example, you could use an array of Integers to store the combination to a safe. Or you could use an array of Strings to store the dialogue of a character for a certain scene.
To create an array, first create a regular variable with the data type you want the array to use, and then click the icon to the right of the Variable Type property in the Details Panel and select the “Array” icon (Figure 5-13).
Changing a regular variable into an array
Arrays are made up of slots that each store one of the values of the list. The proper term for one of these slots is an index. Arrays in Unreal are “zero based” which means the first index is 0. So the second index is 1, the third index is 2, and so on. Each value stored in the array is known as an element of the array.
The ForEachLoop Node is used to iterate through the elements of an array. It has an input pin called Array where you can input the array you wish to use. It has an output execution pin called Loop Body that will be activated once for each element in the array. Each time the Loop Body pin fires, the Node’s Array Element pin will contain the value of the current element, and the Array Index pin will contain the index number of the current element. The output execution pin Completed will fire once all the elements have been iterated through.
The example shown in Figure 5-14 will loop through an array of Strings named “My Inventory” and output each value to the screen.
The ForEachLoop Node will loop through every element of an array
The Add Node can be used to add another element to the end of an array. It has an input pin for the array itself and an input pin for the variable containing the value to add.
In Figure 5-15, whatever value the variable “New Item” contains will be added to the end of an array named “My Inventory” whenever the P key is pressed on the keyboard.
Pressing P will cause New Item to be added to the end of the My Inventory array
The Add Node will add a new element to the end of the array, but to add a new element somewhere in the middle, you need to use the Insert Node (Figure 5-16). It has a pin to specify the array, a pin to specify the value you want to add, and a pin to specify at which index the value should be inserted.
The Insert Node
When a value is inserted, the length of the array increases by one, all the values at the specified index and above get moved one index higher, and then the new value is assigned to the specified index. So the Insert Node inserts values in between other values without erasing any data.
Set Array Element Node
If you want to replace the value of a certain index, you need to use the Set Array Element Node (Figure 5-17). Unlike the Insert Node, this Node will overwrite the value at the specified index and won’t change the location of any of the other values.
The Set Array Element Node
The Set Array Element Node has a Size to Fit pin. As an example, let’s say that at the time the Node fires, the array being used has four elements (indices 0 to 3). Also, let’s say you specify that you want the new value to go into index 6. If Size to Fit is False, this won’t work, because index 6 doesn’t exist. The game won’t crash, the array simply won’t change in any way. But if Size to Fit were True in this scenario, the length of the array would increase to 7, so that there is an index 6. Index 6 would get set to the new value specified, and indices 4 and 5 would simply remain empty.
Removing Elements from an Array
When you want to remove elements from an array, there are a few ways to do this. The Clear Node (Figure 5-18) simply deletes all the elements of an array. The Remove Index Node (Figure 5-19) will delete the element at the specified index, and then shift any values at higher indexes down one. The Remove Item Node (Figure 5-20) deletes elements based on their values, deleting any element whose value matches the one specified. The Remove Item Node also has a Boolean pin that outputs True or False based on if any matches were found.
The Clear Node
The Remove Index Node
The Remove Item Node
Retrieving Elements from an Array
When you want to retrieve the value of a certain element, you need to use a Get Node (Figure 5-21) and specify the index of the element, and it will output its value. This is a different kind of Get Node than the one created by dragging the variable into the graph. This Get Node can be found in the Utilities ➤ Array category of the Node Menu.
The Get Node in the Utilities ➤ Array category
Contains Item Node
When you just want to know whether or not an array contains a certain value, you can use the Contains Item Node (Figure 5-22). You specify the value you want to search for, and it will output True if that value was found and False if it was not.
The Contains Item Node
Find Item Node
If you need to know the index that a certain value is located at, you can use the Find Item Node (Figure 5-23). This will return the index of the first element of the array that matches the value specified. If no match is found, this will return a value of -1.
The Find Item Node
Length Node and Last Index Node
You can use the Length Node (Figure 5-24) when you want to know how many elements an array has and the Last Index Node (Figure 5-25) when you want to know its highest index number. Because arrays in Unreal Engine are zero based, the last index of an array will always be one less than its length.
The Length Node
The Last Index Node
A function is a procedure or routine meant to carry out a specific task or series of tasks. Functions are not unique to Unreal Engine. A function is a concept that comes from mathematics and computer science. In computer science and programming, a function is a specific block of code. By extension, in Unreal Engine, a function is a specific Event Graph of Nodes. The entire Event Graph for a function gets encapsulated (contained) within a single Node that can then be used without having to worry about the details inside it.
To create a new function, go to the My Blueprint tab, look for the Functions category, and then click the Add button (Figure 5-26). Whenever you create a new function, it will automatically open that function’s Event Graph and add its Entry Node (Figure 5-27). The Entry Node is the Node that will fire whenever the function is called.
New functions can be added in the My Blueprint tab
The Entry Node for a function named “Welcome Message”
Functions can have inputs and outputs so that data can be passed into and out of the function. To add an input or output, go to the Details Panel and click the Add button under the Inputs or Outputs category, depending on which you want to create (Figure 5-28). You can then define the name and data type of the input/output.
Clicking these Add buttons will create either an input or output for your function
When an input is created, looking “outside” of the function, at its single-node encapsulated form, you will see the input created as an input pin. “Inside” of the function, the data that gets passed to that input pin can be retrieved through a corresponding output pin that gets added to the Entry Node.
Creating an output variable will create a Return Node within the function. The Return Node will always be the last Node of a function, and it will contain input pins for each of your output variables so that you can pass that data back out of the function (these will appear as output pins on the Function Node itself).
As an example, Figure 5-29 shows a function that takes a name as input and then outputs a message using that name.
The “inside” of the Welcome Message function
It has one input – a String variable named “First Name” – and one output, a String variable named “Message.” It retrieves First Name from the Entry Node and passes that to an Append Node where it combines the name with other Strings to form a greeting. That greeting is then passed to the Return Node. Figure 5-30 shows an example of the function in use.
The Welcome Message function in use
As soon as the Level begins, it will call the Welcome Message function. The name “David” is passed in as the value of First Name. This is the value that will be retrieved from the Entry Node within the function. The message that is created inside the function, and gets passed to the Return Node, is the message that is being retrieved here and then passed to the Print String Node.
Advantages of Using Functions
Using functions has many advantages. The main advantage is reusability. For example, if you wanted to use the preceding Welcome Message function dozens of times throughout your game, with several different characters with different names, you don’t want to have to write the logic every single time, for each character, every time it is used. It would be easier to just write it once and be able to use it over and over again. This also makes it much easier to make changes, since the change only needs to be made in one place.
Another advantage is reliability. If you use a function that’s already been used, and thus tested, over and over again, there’s a much better chance that that function is free of mistakes than logic you just wrote. For example, many of the built-in functions in Unreal Engine have now been used repeatedly by numerous companies and developers, and thus any bugs they may have once contained have already been reported and fixed.
A third advantage of functions is readability. While the Welcome Message function example is very small, functions could contain hundreds or even thousands of Nodes. But no matter how many nodes a function contains, it will always get condensed down into just one Node. So by hiding away the “guts” of your logic in this way, it makes it much easier to understand the logic of your game at a high level.
In the Graph category (Figure 5-31), the first property, Description, is used to briefly explain what the function does. Whatever this is set to will appear in the tool tip message that pops up whenever you hover over a function. So if you come back to this function later, or someone you’re working with comes across it, this makes it much easier to quickly understand what a function does without having to open it up and analyze its logic.
The Category property is used to organize your custom-made functions. For example, you could assign a function to a category called “String,” and then in the My Blueprint tab, it will group the function under that category, along with any other functions you assign to that category.
The Keywords property can be used to add a list of keywords to the function which can be useful if you search for the function later.
If you give the Compact Node Title property a value, it will display the Function Node in a compact form, with the value you entered being displayed in the background.
The Access Specifier property is used to specify what Blueprints are allowed to call this function. With this set to Public, any Blueprint is allowed to call this function. With this set to Private, only the Blueprint that the function belongs to is allowed to call it. For example, if a function was created in the Level Blueprint, and Access Specifier is set to Private, you will only be able to call the function from the Level Blueprint and no other.
The Protected setting is like the Private setting, except that the function can also be called from Blueprints derived from the owning Blueprint. Derived Blueprints will be discussed in Chapter 6.
The next property deals with the concept of Pure vs. Impure functions. A Pure function cannot modify any of the variables of its Blueprint, while an Impure function can.
The final property is Call In Editor. So far, we’ve just been looking at Level Blueprints. But as we’ll see later on, every Actor can have their own Blueprint as well. So if this was a Blueprint for an Actor, and the Call In Editor property was checked, then you could click an instance of that Actor in the Viewport, and in the Details Panel, there would be a button that could be clicked to run this function.
In addition to having a Variables tab within its My Blueprint window, functions also have a Local Variables tab (Figure 5-32). Local variables are variables that can only be used within that particular function and aren’t accessible to the rest of the Blueprint. Because of this, local variables are more memory efficient than regular variables. They also help keep your Blueprint more organized.
The Local Variables tab within a function
In the Node Menu, under “Utilities,” there is a category called Flow Control. This category contains several different Nodes that you can use to control the flow of execution in your Blueprints. This is essential to creating logic.
The first node in the list is the Branch Node (Figure 5-33). The Branch Node takes in a Boolean value as its input and then continues execution either through the True output execution pin if the Boolean value is True or through the False output execution pin if the Boolean value is False.
The Branch Node
For example, when the player tries to open a door, you could have a Branch Node with a Boolean variable that stores whether or not the player has the key. You could connect the False pin to a Node that will play the sound of a locked door trying to be opened and connect the True pin to the sound of a door being unlocked.
Do N Node
The Do N Node (Figure 5-34) means “Do N times” where “N” is the number of times this Node should allow execution to pass through it before it begins to block execution. For example, if N is 5, then the first 5 times execution flows into the Enter pin, it will flow out of the Exit pin. However, the sixth time and beyond that, the flow will not continue out of the Exit pin.
The Do N Node
So execution will be blocked in a Do N Node after the Nth time the Node has been activated, unless execution flows into the Reset pin of the Node. When execution flows into the Reset pin, the counter will be reset to 0, and the Node will be able to execute N more times.
The Counter pin will output an Integer representing the number of times the Do N Node has been activated since the game began or since the last time the Node was reset.
The DoOnce Node (Figure 5-35) is just like a Do N Node where N = 1, with the exception that with the DoOnce Node, you have the option to have the Node start closed. By having the Node start closed, this means that execution must flow through the Reset pin before execution will flow through the Completed pin, even the first time.
The DoOnce Node
DoOnce MultiInput Node
The DoOnce MultiInput Node (Figure 5-36) is like the DoOnce Node except that it allows for multiple In/Out pairs. Additional pairs can be added using the “Add pin” button at the bottom. So if execution flows into the A In pin, it will flow out of the A Out pin. If execution flows into the A In pin a second time, without a reset, nothing will happen, but execution will still be able to flow through the B pins and the C pins.
The DoOnce MultiInput Node
If execution flows into the Reset In pin, all of the pairs will get Reset. The DoOnce MultiInput Node also differs from the DoOnce Node in that it has a Reset Out pin that will be executed when the Reset In pin is executed.
The FlipFlop Node (Figure 5-37) simply alternates between having execution flow out of the A pin and the B pin every time the Node is activated. The first time execution flows into the FlipFlop Node, it will flow out of the A pin, and the second time execution flows into the FlipFlop Node, it will flow out of the B pin, and then the third time, it will flow out of the A pin again, and so on.
The FlipFlop Node
The FlipFlop Node has a Boolean output called Is A that will output a value of True if execution is currently being routed through the A pin and False if execution is being routed through the B pin.
With a ForLoop Node (Figure 5-38), the Loop Body execution output pin is fired a certain number of times, starting from an Integer defined by the First Index and then increasing by 1 until it gets to the Integer defined by the Last Index. The Index pin will output an Integer specifying the index of the current loop. The Completed pin will be executed after the final loop is completed.
The ForLoop Node
The ForLoopWithBreak Node (Figure 5-39) is just like the ForLoop Node, except that it is possible to break the loop before it is finished. If execution flows into the Break pin, the loop will stop immediately and the remaining loops will not be executed.
The ForLoopWithBreak Node
A Gate Node (Figure 5-40) is a Node that can be set to opened or closed . When the Gate is open, execution flow entering the Enter pin will flow out of the Exit pin. When the Gate is closed, any execution flow entering the Node will stop there, and the Exit pin will not fire.
The Gate Node
The next three input pins are used to set the status of the Gate. Any time execution flows into the Open pin, it will open the Gate, and any time execution flows into the Close pin, it will close the Gate. If execution flows into the Toggle pin, it will set the status to whatever it is currently not. So if the Gate was open, the Toggle pin would close it, and if the Gate was closed, the Toggle pin would open it. The Start Closed property will determine whether the Gate starts out Open or Closed.
With a MultiGate Node (Figure 5-41), execution enters a single execution input pin, but it will flow out of only one of the execution output pins. You can use the Add pin button to add as many execution output pins as you like.
The MultiGate Node
If Is Random is unchecked or set to False, then execution will flow out of the output pins in sequential order, starting at the Start Index. With a Start Index of -1, it’s the same as saying that you’re not specifying a Start Index, so it will just go with the default which is 0. Loop will determine whether or not the sequence should start over or if the Node should just block further execution flow.
If Is Random is set to True, then instead of going in sequential order, output will flow out of the pins in random order until each pin has been used. At that point, the Node will either need to be reset or start a new loop, depending on what Loop was set to.
Retriggerable Delay Node
The Retriggerable Delay Node (Figure 5-42) is just like the Delay Node , except that the delay can be reset or “retriggered” if another pulse enters the execution input pin before the delay has finished counting down. So if the duration of the delay is set to 10 seconds, and the Node is activated, and then after 7 seconds the Node is activated again, the delay will start counting down from 10 again.
The Retriggerable Delay Node
With the Sequence Node (Figure 5-43), every time execution flows into the Node, it will flow out of every single one of the output pins. Again, you can use the Add pin button to add as many output pins as you want. When execution flows into the Node, it will fire each of the pins sequentially; however it will do so without any delay, so from the player’s perspective, it will appear as if each of the pins fired at the same time.
The Sequence Node
Once the WhileLoop Node (Figure 5-44) has been activated, the Loop Body pin will fire over and over again, as long as the Boolean value connected to the Condition pin is True. Before each loop iteration, it will check the value of Condition, and once the Condition is False, it will break the loop and execution will flow out of the Completed pin. It’s important to make sure that there is definitely some way for the Condition to eventually evaluate to False, or you will end up with an infinite loop.
The WhileLoop Node
Switches are a way to route the flow of execution based on the value of whatever variable you pass into the Switch. For example, if you create a Switch on Int Node (Figure 5-45), you can connect an Integer variable to the Selection pin, and then when the Node is activated, it will read in the value of the Integer and, based on that value, route execution to one of the output pins.
The Switch on Int Node
By default, the only output pin is the Default pin. The Add pin button can be used to create more output pins and will create them starting with the value of the Node’s Start Index property and then incrementing by 1 each time the button is clicked. If you want to delete one of the pins you added, you just need to right-click that pin and click “Remove execution pin.”
You can also do a Switch on other data types. For example, you could use the Switch on Name Node (Figure 5-46). This will work the same way as the Switch on Int Node, with the exception that you will need to specify the text to compare against for each of the output pins. You can do that by going over to the Details Panel, expanding the Pin Names property, and entering the text you want each pin to check for.
The Switch on Name Node
Accessing Actors Within Blueprints
To really get use out of your Blueprints, you’re going to want to be able to access the Actors in your Level in order to be able to read their data, make decisions based on that data, and to manipulate the Actors in different ways.
In order to get access to an Actor within a Blueprint, that Actor needs to be selected in the Level Editor when you right-click the Event Graph of the Blueprint. When you do so, the Node Menu will have some options at the top relating to that Actor. You can create an Event based on the Actor, you can call a Function on the Actor, and you can also get a reference to the Actor (Figure 5-47). Note that for this to work, the Context Sensitive checkbox needs to be checked.
You can get a reference to the currently selected Actor through the Node Menu
Getting a Reference to an Actor
The example shown in Figure 5-48 uses a reference to a Light Actor to turn that light off two seconds after the Level begins.
This logic will turn a Light Actor off two seconds after the Level begins
The Set Visibility Node takes in a Root Component as the “Target” to perform the action on, and its New Visibility Boolean will determine whether the Node will set the visibility of the target component to True or False. Note that when connecting the reference to the Light Actor to the Target pin, the Engine automatically created a Node in between. This is because the Set Visibility function technically sets the visibility of Components, not the Actors themselves, so the Node is just getting the Root Component of the Light Actor so that the Root Component can be passed in as the target component.
Creating an Event from an Actor
To create an Event from an Actor, select the Actor in the Level Editor, open the Node Menu in the Blueprint, make sure Context Sensitive is checked, then select “Add Event for [Actor Name].” From there, if you expand the Collision menu, there will be an option to create an On Actor Begin Overlap Event (Figure 5-49). This Event will fire whenever another Actor overlaps with this Actor. This Event is often used with Trigger Volumes.
Adding an Add On Actor Begin Overlap Node
The example in Figure 5-50 uses Events to turn a Light on and off when an Actor enters and exits a Trigger Volume named “LightTrigger.”
This logic will turn a light off when an Actor enters a Trigger Volume and will turn it back on once that Actor leaves the Trigger Volume
With Blueprint Classes, you can create Blueprints out of existing Actors. By creating a Blueprint from an Actor, you can add data and functionality to that Actor, essentially creating your own custom version of that Actor type.
Unreal comes with several built-in Blueprint Classes, such as Pawn, Character, Player Controller, Game Mode Base, and many more. We’ll start to see some of these in the next chapter, but this section will focus on creating your own Blueprint Classes.
To create a Blueprint from an Actor, select it, and then in the Details Panel, click the blue “Blueprint/Add Script” button (Figure 5-51). Then select the folder path where you want to save the Blueprint, give it a name, and click “Create Blueprint.”
The Blueprint/Add Script button
So far in this book, the only Blueprints have been Level Blueprints, which only have an Event Graph. But for Blueprints of Actors, there is also a Viewport tab and a Construction Script tab. The Viewport tab allows you to see what your Actor looks like and also allows you to add Components to it. The Construction Script is something that will be run just before the Actor gets created, so it’s useful for performing any initialization you might need to do on the Actor to get it ready for gameplay.
Blueprint Class Example
The example in Figure 5-52 is a Blueprint that has been created from a Point Light Actor. The logic will cause the Light to turn on and off every second.
This logic will cause a Light Actor to turn on and off every second
The Toggle Visibility function is like the Set Visibility function, except instead of using it to specifically set a visibility property to True or False, it will simply toggle the property to the opposite of whatever it’s currently set to. So if the visibility was True, the function would set it to False, and vice-versa.
Because this is the Blueprint for the Point Light, the Editor assumed that the Light is the desired target and automatically connected the Light Component of the Light to the Target pin when the Toggle Visibility Node was created.
When the game loads and the Actor is first created in memory, its Event BeginPlay Node will fire. Then the Delay Node will delay flow for one second before the Toggle Visibility Node is activated. The output execution pin of the Toggle Visibility Node has been connected to the input execution pin of the Delay Node. This creates a loop that will cause the Light to turn on and off every second for the duration of the Actor’s existence.
One of the major advantages of Blueprint Classes is that they are reusable. The preceding Blueprint of a custom Light Actor can be used just like any other Actor. If you browse to it in the Content Browser, you can drag and drop as many instances of it as you want. An instance is an individual copy of an object made from a Blueprint.
So if you dragged five copies of the Light into the Viewport, let’s say, you would have five instances of it in your Level, each with their own copy of the Nodes in the Blueprint they were created from. Think of, for example, identical human quintuplets. Each was created from the same Blueprint (their DNA), but each of them can exist independently in the world.
Instances made from the same Blueprint have the same variables, but they maintain their own copies of that variable, so the value stored in that variable can be different for each instance, a concept explained in the following section.
Instance Editable Variables
When you add a variable to a Blueprint Class, it is, in essence, adding a custom property to that Actor. The example in Figure 5-53 builds upon the earlier example and adds a Float variable named Light Toggle Duration to the Blueprint and uses that variable as the Duration of the Delay Node.
A Float variable named Light Toggle Duration has been added to this example
Right now, this isn’t doing anything different than it was doing before, but that can be changed by making this variable Instance Editable.
There are two ways to make a variable Instance Editable. One way is to use the icon in the My Blueprint tab, which will toggle between the image of an eye open and an image of an eye closed. When the eye is open, that means that the variable is Instance Editable. You can also use the Instance Editable checkbox in the Details Panel.
If a variable is set to Instance Editable, its value can be changed in the Level Editor. With the Light Toggle Duration variable set to Instance Editable, if you select an instance of the Light Blueprint in the Level Editor, that variable will now appear in the Details Panel, as shown in Figure 5-54.
The variable named Light Toggle Duration now appears in the Details Panel when an instance of the Light Blueprint is selected in the Level
Now you have the ability to easily set a different duration for each instance of the Actor. You could drag in several instances of the Actor, give them each a different Light Toggle Duration, and they will all turn on and off at different rates. This is the power of Blueprint Classes. You can create your own custom Actors, reuse them as many times as you like, and modify their individual properties.
Timelines are used to create simple animations, such as changing the location, rotation, or color of an object. To add a new Timeline Node, right-click the graph, select “Add Timeline…” from the bottom of the menu (Figure 5-55), and give the Timeline a name. To edit a Timeline, double-click it to open it in the Timeline Editor.
A new Timeline Node can be added from the Node Menu
Tracks and Keys
To add a new track to a Timeline, use one of the buttons in the upper-left corner of the Timeline Editor (Figure 5-56). A track is used to specify what value or values the Timeline should be outputting at any given point in time. For example, the first button with the “f” on it is used to add a Float track which is used to output single Float values.
These buttons are used to add new tracks to a Timeline. The first button creates a Float track
A track is represented by a graph. The time, in seconds, from the start of the Timeline, is represented horizontally. The value that gets outputted is represented vertically. To specify what value should be outputted at what time, you need to add a key to that point on the track’s graph (Figure 5-57). To add a key, hold down Shift on the keyboard and left-click the graph.
The orange diamond in this figure is called a key
To change the placement of a key, either left-click it and drag it to where you want or use the boxes at the top of the graph to enter the X and Y values manually. To move around the graph, right-click and drag the mouse. To zoom in and out, use the scroll wheel of the mouse, just like in a Blueprint graph.
Figure 5-58 is an example of a Timeline that is used to animate a Light Actor, so that its light starts out completely dark, gradually gets brighter, and then gradually gets dimmer again. The Timeline consists of a single Float track that will be used to feed values into the Light’s Intensity property.
The line that connects the keys in a Timeline is called a curve
The line that connects the keys is called a curve and represents what value the Timeline Node will output at any given time during the animation. In this case, at the start of the animation, the Timeline Node will output zero, then it will gradually output a higher and higher value, until at 2.5 seconds, it is outputting a value of 100,000. Then, for the next 2.5 seconds, the value gradually decreases, until it reaches zero again.
This value will get outputted from an output pin on the Timeline Node. For each track you create, it will create a new output pin on the Timeline Node that will have the same name as the track and will output the value for that track. In Figure 5-59, the output of the track is connected to a pin that will set the Intensity property of the Light Component of a Light Actor.
Due to the curve of the track created for this Timeline, this logic will cause a light to gradually get brighter, then gradually get dimmer again
When the Play execution pin is activated, it will cause the Timeline to start playing. For the next 5 seconds (the length of the Timeline), for each tick of gameplay, the Update pin will fire, causing the Set Intensity Node to fire. Each time the Set Intensity Node fires, it will receive a different value from the track based on that track’s curve and the current playback point of the Timeline.
That’s the basics of how Timelines work. You create a curve on a track to output different values across time and then use those values to update some property during each tick of gameplay.
Other Types of Tracks
The preceding example used a Float track, but there are other types of tracks as well. If you wanted to create a track to change a Vector value, such as an object’s location, you would use the button to the right of the Float track button to create a Vector track. By gradually changing an object’s location over time, you can create a simple movement animation.
To the right of that is a button that is used to create an Event track, which can be used to specify at what points in time certain Events should fire. To the right of that is a button used to create a Color track which can be used to gradually turn one color into another color.
Add an Existing Curve to a Track
The button to the right of the Color track button can be used to add an already existing curve to a new track. If you select a curve asset in the Content Browser and then click the button, it will create a new track and add that curve to it.
To add an existing curve to the current track, select the curve in the Content Browser, then click the arrow beneath the text “External Curve” to the left of the track you want the curve added to (Figure 5-60).
Existing curves can be added to a track
To save a curve you create so it can be used again later in the preceding manner, right-click the graph and select “Create External Curve” to save the curve as an asset in the Content Browser.
To the right of the create track buttons, there are a few options you can set for your Timeline (Figure 5-61). The first box allows you to set the length of the Timeline. To the right of that is the Use Last Keyframe? option. If this is unchecked, the very last tick of the animation will be ignored. This is useful when looping, to prevent skipping in the animation when the loop starts over.
If the AutoPlay option is checked, the Timeline will begin playing as soon as the Level (or Actor) is created, even if it’s not connected to an Event BeginPlay Node. With the Loop option checked, the animation will start over from the beginning once it reaches the end. The Replicated option will cause the animation to be replicated across all clients during a multiplayer game.
The final option is Ignore Time Dilation. “Time dilation” is a feature in UE4 where you can slow down or speed up time in your game. With this option checked, the Timeline will ignore any time dilation settings and just play at normal speed.
Timeline Node Pins
When the Play pin (Figure 5-62) fires, the Timeline will start playing from its current position. So let’s say the Timeline starts at zero, and the Play pin fires, and then two seconds into the animation the Stop pin gets executed. At that point, the animation will pause at the two-second mark. If the Play From Start pin was executed, the animation would go back to the zero-second mark and play from there. But if the Play pin was executed at that point, the animation would continue playing from the two-second mark.
The pins of the Timeline Node
The Reverse pin will cause the animation to start playing in Reverse from its current position, and the Reverse from End pin will move the animation to the end and then start playing in Reverse from there. The Set New Time pin will move the animation to whatever time is specified in the New Time pin.
The Finished pin fires when the animation is complete. The Direction pin will contain a value of either Forward or Reverse, based on which direction the Timeline is playing at that particular moment.
If your Blueprints aren’t behaving the way you expect, there is a feature called “debugging” you can take advantage of to help diagnose the problem. With debugging, you can watch the flow of execution move through your Blueprint in real time, as the game runs, or you can pause the game and view the state of the Blueprint at that time. You will be able to see what Node is currently being processed, which Nodes were already processed and in what order, and what values the Blueprint’s variables currently contain. You can also step through the Blueprint one frame at a time or, using Breakpoints, one Node at a time.
When viewing a Blueprint while the game is running, every time a Node is activated, the wire leading into its execution pin will pulsate for a few seconds and change color, as seen in Figure 5-63. Some types of Nodes will display extra information. For example, the Delay Node will display how much time is remaining until the delay finishes, also seen in Figure 5-63.
A Level Blueprint shown while the game is running. Execution has just flowed into the Delay Node, as indicated by the pulsating wire and the information above the node
While the game is running, you can pause or stop it from the Toolbar of the Level Editor or Blueprint Editor. While paused, you have the option to resume, frame skip, or stop (Figure 5-64). Clicking the Frame Skip button will advance the game by one frame of gameplay, then pause the game again.
While the game is paused, these controls will be available in the Toolbar
While the game is running or paused, you can hover over the name of a variable in a Get or Set Node to see the value of the variable at that time, as seen in Figure 5-65. You also have the option to watch a variable by right-clicking its name in a Get or Set Node and then clicking “Watch this value.” This will cause the value of the variable to be displayed above the Node at all times, without having to hover over it (Figure 5-66).
Hovering over a variable while the game is running or paused allows you to see the variable’s current value
Watching a variable causes that variable’s value to be displayed at all times
In order to debug an instance of a Blueprint Class, you must specify the instance in the Debug Filter dropdown menu on the right side of the Blueprint’s Toolbar (Figure 5-67). You can use the magnifying glass icon to the right of the dropdown to take you directly to that instance within the Level.
Use this dropdown to select which instance of the Blueprint to debug
A Breakpoint will cause execution of the game to pause automatically when it reaches the Node on which that Breakpoint has been placed.
To add a Breakpoint, right-click a Node and select “Add breakpoint” from the menu. Alternatively, you can select a Node and press F9 on the keyboard to toggle a Breakpoint on or off for that Node.
If a Node has a Breakpoint attached, there will be a red circle in the upper-left corner of the Node. Once that Node is reached, execution will pause, and there will be a red arrow pointing at the Node, as shown in Figure 5-68.
The Breakpoint attached to this Node has caused execution to automatically pause here, as indicated by the red arrow
When execution is paused due to a Breakpoint, additional controls appear in the Toolbar that aren’t available when you pause execution manually (Figure 5-69).
These controls are available when execution flow reaches a Breakpoint
The Find Node button will take you directly to the Node that execution is currently paused at. This is useful for large Blueprints with hundreds or even thousands of Nodes. If the current Node is a custom function, you can use the Step Into button to open that function and see execution flow at that level of detail. If you currently have a function open and want to go back to the Node that calls the function, you can click the Step Out button. For all Nodes, you can click the Step Over button to execute that Node and move to the next Node where execution will pause once more.
In this chapter, you got a solid foundation in the complex topic of Blueprints. In the next chapter, you will build upon this foundation and continue your study of Blueprints by learning how you can use them to create players and an input system.