In this tutorial series, you’ve used level design and game mechanics to engineer gameplay for your players. The puzzles, keys, and doors that you’ve built are all parts of a gameplay loop.
A gameplay loop is a series of actions that the player repeats, making up the core of your gameplay.
You still need to close the loop for the level you’ve built. In this tutorial, you’ll build a win screen that communicates to the player that they’ve completed the current level. You’ll also build a level transition point that verifies a win condition and takes the player to the next level.
Once your level is complete, you’ll explore ways to expand on everything you’ve learned in this track.
A win condition is an objective the player must meet in order to complete a gameplay task, quest, level, or game. Your gameloop must provide the means to meet the win condition. In nonlinear games, you might have more than one win condition.
Before You Begin
This tutorial assumes you already have an understanding of the following topics, which are covered in the previous sections of Design a Puzzle Adventure:
Widget Blueprints
Blueprints
Variables
Collision Volumes
Play-In-Editor Mode
Parent and child assets
You’ll need the following assets from Traps and Damage:
WBP_EliminatedScreenWidget BlueprintBP_KeyBlueprint ClassEnum_KeyTypeEnumeration
Build the Level End
Even though you’ve finished building your level’s core gameplay, the transition point is a good opportunity to give players an interesting way to finish your level. In this case, you’ll build a jump pad to launch players onto a raised platform. Later on, you’ll place the level transition point on the platform.
Build a Platform
To build an elevated platform in one of your rooms, use the SM_Cube and SM_Cylinder static meshes in the LevelPrototyping > Meshes folder.
The tutorial sample level uses a 3.5m square platform with four columns that looks like this:
If you’d like to copy these blockout pieces into your level, copy the snippet below. If you’ve been following along with the sample level, these shapes will appear near the back corner of Room 3. You can move them as desired.
To copy the platform, follow these steps:
Click Copy Full Snippet.
Command LineBegin Map Begin Level Begin Actor Class=/Script/Engine.StaticMeshActor Name=StaticMeshActor_785 Archetype="/Script/Engine.StaticMeshActor'/Script/Engine.Default__StaticMeshActor'" ExportPath="/Script/Engine.StaticMeshActor'/Game/AdventureGame/Designer/Lvl_Adventure.Lvl_Adventure:PersistentLevel.StaticMeshActor_785'" Begin Object Class=/Script/Engine.StaticMeshComponent Name="StaticMeshComponent0" Archetype="/Script/Engine.StaticMeshComponent'/Script/Engine.Default__StaticMeshActor:StaticMeshComponent0'" ExportPath="/Script/Engine.StaticMeshComponent'/Game/AdventureGame/Designer/Lvl_Adventure.Lvl_Adventure:PersistentLevel.StaticMeshActor_785.StaticMeshComponent0'" End Object Begin Object Name="StaticMeshComponent0" ExportPath="/Script/Engine.StaticMeshComponent'/Game/AdventureGame/Designer/Lvl_Adventure.Lvl_Adventure:PersistentLevel.StaticMeshActor_785.StaticMeshComponent0'" StaticMesh="/Script/Engine.StaticMesh'/Game/LevelPrototyping/Meshes/SM_Cylinder.SM_Cylinder'" StaticMeshImportVersion=1 bUseDefaultCollision=False StaticMeshDerivedDataKey="STATICMESH_FD1BFC73B5510AD60DFC65F62C1E933E_228332BAE0224DD294E232B87D83948FQuadricMeshReduction_V2$2e1_6D3AF6A2$2d5FD0$2d469B$2dB0D8$2dB6D9979EE5D2_CONSTRAINED0_100100000000000000000000000100000000000080FFFFFFFFFFFFFFFFFFFFFFFF000000000000803F00000000000000803F0000803F00000000000000003D19FC1626C9B2485E57DB4B8EC731318B8215AE8D46FAD400000000010000000100000000000000010000000100000000000000000000000100000001000000400000000000000001000000000000000000F03F000000000000F03F000000000000F03F0000803F00000000050000004E6F6E65000C00000030000000803FFFFFFFFF0000803FFFFFFFFF0000000000000041000000000000A0420303030000000000000000_RT00_0"In Unreal Editor, ensure the viewport or Outliner is the active panel, and press Ctrl + V.
Next, you’ll add a jump pad that launches the player up onto the platform.
Use the Jump Pad
While you could build a jump pad from scratch, this would cost you time. In a development environment, where time is often limited, it can be useful to import prefabricated (prefab) assets instead of making your own. Choosing prefab that aligns with the visual style of your game can speed up development without standing out.
For this tutorial, you’ll use an asset that comes with the First Person Template, BP_JumpPad.
To integrate BP_JumpPad, follow these steps:
In the Content Browser, navigate to LevelPrototyping > Interactable > JumpPad.
Drag an instance of
BP_JumpPadinto your level, in front of the platform. If you want to match the exact location shown in this tutorial, setBP_JumpPad’s Location to1790,-1460,10.
Your level should now look similar to this:
It’s time to test your work. First, make sure any BP_Enemy has a Max Speed of 0. This ensures you’re not dealing with moving enemies while testing.
Right-click in the viewport and select Play From Here to playtest your level from your current location. Step onto the jump pad and try to reach the platform.
Notice that even with the jump pad’s boost, your player character can’t reach the platform. You can solve this by adjusting the jump pad’s Velocity parameter.
Like the many editable variables you’ve created in your blueprints, the Velocity parameter is a premade, instance-editable variable for the jump pad asset.
To adjust the Velocity, follow these steps:
Select
BP_JumpPadin the viewport.In the Details panel, set Velocity (Z) to
1000.
Now, test your level again. You should be able to jump onto the platform.
Next, you’ll create a win screen that displays when the player completes the level.
Create a Win Screen
You’ll create a win screen by using a widget blueprint, similar to the WBP_EliminatedScreen game-over screen you created in Traps and Damage. Since these two screens are so similar, you’ll use WBP_EliminatedScreen as a starting point.
To create a win screen by duplicating your game-over screen, follow these steps:
In the Content Browser, navigate to AdventureGame > Designer > Blueprints > Widgets.
Right-click
WBP_EliminatedScreenand click Duplicate.Name the new widget blueprint
WBP_WinScreenand double-click it to open it in the Widget Editor. Your Widgets folder should now look like this:To change the message, click the Text widget in the Hierarchy.
In the Details panel, under the Content heading, next to Text, enter
Level Complete! …Loading the Next Level.in the text field.Under the Appearance heading, next to Color and Opacity, click the color swatch to open the color picker. Choose a color you like, or set the Hex sRGB value to
FFE000FFto follow along.The win-screen text is shorter, so you can increase its size to fill the screen better. Under the Font heading, change the Size to
72or a size you feel is most readable.Save, Compile, and close the widget editor.
Next, you’ll create a level transition point.
Create a Level Transition
A level transition loads the next level. You can trigger a level transition in many ways; when a player finishes a cutscene, collects a pickup, or reaches the end of a level.
In this tutorial, the level transition will be a Blueprint that triggers when two things occur:
The player overlaps the level transition.
The win condition is met.
To create a new Blueprint, follow these steps:
In the Content Browser, navigate to AdventureGame > Designer > Blueprints.
Right-click and select New Folder. Name this folder
LevelTransition.Inside the Level Transition folder, right-click and select Blueprint Class to create a new Blueprint.
Select Actor as the parent class.
Name this new Blueprint
BP_LevelTransitionand double-click it to open it in the Blueprint Editor.
Your Level Transition folder should now look like this:
Much like the other blueprints you’ve created so far, your level transition needs the following:
A static mesh that the player can see during runtime.
A collision shape to detect when the player collides with it.
Logic to power the interaction.
Let’s build out the mesh and box collision first, and then move onto the logic.
To create a static mesh and collision shape, follow these steps:
In the Components tab of
BP_LevelTransition, click the Add button and search forcubeto create a new static mesh.Name this static mesh
TransitionPoint.With TransitionPoint selected, in the Details panel, set its Scale to
3.0,3.0,0.1. This is sized to fit the sample level’s end platform; you can resize yours to what works best in your level.Back in the Components tab, select DefaultSceneRoot. Click the Add button and search for
box collisionto create a collision shape.Name the box collision
LevelTrigger.With LevelTrigger selected, in the Details panel, set its Scale to
4.0,4.0,2.0. Set its Z location to55.0.If the box collision isn’t appearing as the correct shape, make sure it’s not a child of TransitionPoint.
Save and Compile.
Build with Logic
BP_LevelTransition should do five things in sequence:
Check for overlap.
Verify the win condition.
Disable player input.
Display the win screen.
Load the next level.
Step by step, let’s create the logic that powers these interactions.
Check for Overlap
To build logic that checks for overlap, follow these steps:
In the MyBlueprint tab of
BP_LevelTransition, In the Variables section, click the + button to create a new variable and name itOtherActor.Set the pin type to Actor (Object Reference).
In the EventGraph, delete the three existing event nodes. You won’t need them.
In the Components tab, right-click on LevelTrigger and click Add Event > Add OnComponentBeginOverlap. This function checks when an object overlaps the collision shape.
From the Exec pin, drag out and create Set Other Actor.
Connect both Other Actor pins.
Next, you’ll build logic that verifies the win condition.
Verify the Win Condition
In this tutorial, the win condition will be collecting all three keys. The reason for choosing this particular condition is to anticipate and prevent game-breaking player actions.
For example, if the win condition was “player overlaps the level transition” and a player finds a way over the room walls, they could bypass your entire level. By using the keys as a win condition, the player must complete your game loop — even if they find a way past the walls and doors.
While it's impossible to predict every bug, design that thinks ahead can prevent players from breaking your game.
To create an array to store the key data, follow these steps:
In the MyBlueprint tab of
BP_LevelTransition, click the + button to create a new variable and name itHeldKeys.Set the pin type to Enum Key Type and the container type to Array.
From the Exec pin of the Set node, drag out and create fnBPIGetKeys.
From the Target pin, drag out and create Get Other Actor.
From the Exec pin on fnBPIGetKeys, drag out and create Set Held Keys.
Connect both Held Keys array pins.
To create an enum key type to set a win condition, follow these steps:
Create a new variable and name it
RequiredKeys. This is your win condition.Make sure the pin type is Enum Key Type and the container type is Array.
In the Details panel, enable Instance Editable and set the Category to
Setup.Compile the Blueprint to gain access to the Default Value. Click the + button to add three new elements to the array.
Click the index dropdown menus and set the indexes to Yellow, Blue, and Red.
You’ll create a boolean to verify whether the condition is met or not. A For Each Loop with Break will cycle through the HeldKeys array to check for each key — and break if there are keys missing.
To build logic that checks for missing keys, follow these steps:
Create a new variable and name it
FoundAllKeys.Set the pin type to Boolean and the container type to Single.
From the Exec pin of SetHeldKeys, drag out and create a For Each Loop with Break.
From the Array pin of the For Each Loop, drag out and create a Get Required Keys node.
From the Loop Body pin on the loop, drag out and create a Branch.
From the Condition pin, drag out and create a Contains Item (Array) node.
From the Target Array pin on the Contains node, drag out and create Get Held Keys.
Connect the Item to Find pin on the Condition node to the Array Element pin on the loop node.
From the True pin of the Branch node, drag out and create Set Found All Keys. Click the checkbox next to FoundAllKeys to set it to true.
From the False pin of the Branch node, drag out and create Set Found All Keys. Leave the checkbox empty and connect the Exec pin to the Break pin on the For Each Loop.
You have three more steps to do in the sequence we looked at earlier, but only if the player has all keys:
Disable player input.
Display the win screen.
Load the next level.
To use the FoundAllKeys result to start a sequence of logic, follow these steps:
From the Completed pin of the For Each Loop, drag out and create a Branch.
Drag out from the Condition pin and create Get FoundAllKeys.
From the True pin of the Branch node, drag out and create a Sequence node.
Since you need to build three actions in this sequence, click the Add Pin button.
Let’s move onto the next step in the sequence; disabling player input.
Disable Player Input
While displaying the win screen, disabling player input prevents players from moving around and receiving unintended damage.
To disable player input, follow these steps:
From the Then 0 pin of Sequence, drag out and create a Disable Input node.
From the Target pin of the Disable Input node, create Get Other Actor.
From the Player Controller pin, drag out and create a Get Player Controller node.
Next, you’d build logic to display the win screen.
Display the Win Screen
To display your WBP_Winscreen widget, follow these steps:
From the Then 1 pin of the Sequence node, drag out and create a Create Widget node.
Set the Class to WBP_WinScreen.
From the Exec node on the Create Widget node, drag out and create an Add to Viewport node.
Connect the Return Value pin on Create Widget to the Target node on Add to Viewport.
Do you see an issue with this logic? For now, you’ll move on and build the final step without fixing the issue. Later on, you’ll playtest the level to discover the problem and build a solution.
Load the Next Level
For this tutorial, you’ll use your current level as a placeholder for the next level. When you're designing your own game, the transition point should take players to a brand new level.
To build logic that loads the current level, follow these steps:
From the Then 2 pin of the Sequence node, drag out and create an Open Level (by Object Reference) node.
From the Level pin of Open Level, drag out and search for Promote to Variable. This will force the creation of a World-type variable.
You can also create this variable through the MyBlueprints tab, but the World pin type can be difficult to locate.
With the World variable selected, in the Details panel, rename the variable to
NextLevel.Add it to the Setup category and enable Instance Editable.
Compile your Blueprint to gain access to the variable’s Default Value and set it to the level you’d like to load. If you’re following along with this tutorial, set it to
Lvl_Adventureto loop the current level.Save and Compile.
It’s time to test your work. Drag an instance of BP_LevelTransition onto the raised platform. Then, give yourself easy access to the keys to meet the win condition. You can do this by placing instances of the yellow, blue, and red keys you created in Create a Key into the same room.
Your level should now look something like this:
Right-click in the viewport and select Play From Here to playtest your level from your current location. If you jump onto the platform and activate the level transition, you’ll notice the screen freezes and the next level opens without giving the player time to read the win screen message.
You’ll solve this issue in the next section.
Create a Delay
This tutorial uses Open Level to close the current level and open the next as a new game instance. During loading, Open Level freezes the game. Depending on the player’s system, that freeze might be too short (to read your win screen), or too long (appearing as if the game has crashed).
Many games, even those using Level Streaming, utilize loading screens to let the player know that the game is working properly and that they should wait. Loading screens also solve another problem; long, frequent, or boring wait times can break immersion and cause frustration. Loading screens often include tips, animation, or audio to retain the player’s attention while they aren’t playing.
To solve this technical issue with design, you’ll create an intentional delay that achieves the following:
Equalize the loading times for all players.
Ensure the player has enough time to read the win screen.
Disguise loading times by giving the player something to look at.
To insert a delay, follow these steps:
Open up
BP_LevelTransition. In the MyBlueprint tab, click + to add a new variable and name itLevelLoadDelay.Set the pin type to Float.
In the Details panel, enable Instance Editable and set the Category to Setup.
Compile the blueprint to gain access to the Default Value. Level Load Delay will set the amount of time you want the delay to last. To follow along, set it to
5.0seconds.In the EventGraph, navigate to the Sequence node. To insert a delay, drag out from the Then 2 pin and create a Delay node.
From the Duration pin, drag out and create Get LevelLoadDelay.
Save, Compile, and close your blueprint.
Your final BP_LevelTransition EventGraph should look like this:
Now, test your level again. When you overlap the level transition point, the win screen should display, the background should blur, and player input should be disabled for five seconds before your player character appears in the next level.
Before you playtest your level for the final time, remember to remove the keys from Room 3 and set BP_Enemy’s Max Speed back to 200.
From Concept to Creation
Let's take a look at the blockout we created in Project Setup and Level Blockout compared to the final level. From its initial design, our level design and gameplay loop changed to address bugs, create new features, or work around limitations that playtesters discovered during development.
By blocking out your level, working modularly, solving technical problems with design, and keeping your assets organized, you can stay flexible when limitations or new features change the course of your game’s development.
By completing this track, you've taken a level from concept to playable demo. You now have the building blocks to design more than just one level. You can combine switches, traps, keys, doors, and enemies in unlimited ways to design new gameplay loops in your own style. When connected together, each level becomes part of a much larger project; an entire game.
Example Project
Below is a link to download the final project that you can build using this tutorial series of documentation. You can use this example project to see what your final project might look like, or as a reference to see how we built and designed the project.
(Download size: 75 MB)
To open the project, unzip the file and move the adventuredesigner folder to your Unreal Projects directory (by default, find this in C:\Users\UserName\Documents\Unreal Projects).
Next Up
To continue working on your level by adding materials, lighting, post-process effects, sound, and visual effects, try the Artist Track Tutorial Series:
Art Pass for a Puzzle Adventure Game
Learn how you can apply art workflows with materials, sounds, and visual effects to the Puzzle Adventure game.
If you'd like to walk through building another blueprint, continue to this bonus module of the Designer Track Tutorial Series:
Bonus: Spawn New Cubes
Add a new mechanic to your puzzle adventure game where BP_Cube actors spawn to a specified limit.
If you are interested in packaging your project, as a standalone program to test and share, see the following documentation:
Packaging Unreal Engine Projects
Packaging Unreal game projects for distribution.