Now that the player can pick up keys in the game, you’ll add the functionality to unlock and open doors when the player has picked up the required key. In this part of the tutorial, you will modify the BP_DoorFrame blueprint and explore Functions in Blueprints.
Unlockable doors provide a way to control the flow of the game and provide a sense of progression to the player. The project we are currently working on is divided into rooms. Therefore, picking up keys to unlock doors provides a logical progression path to the player.
Before You Begin
Make sure you understand these topics covered in the previous sections of the Design a Puzzle Adventure tutorial series:
Blueprint basics, including Blueprint Interfaces.
Creating variants of an object using a Map variable.
You’ll need the following assets created in the previous tutorial, Create a Key:
BP_KeyBPL_FPGameBlueprint Function libraryBPI_PlayerKeysBlueprint InterfaceThree
BP_DoorFrameinstances placed in your level between rooms or hallways.
Add Color Options to the Door
Since the first-person template already has a door blueprint, you can modify the existing blueprint to add the functionality of unlocking doors with a key.
Your door needs a few things to work with the key system you defined in the previous part of this tutorial. Just like the key, your door needs to know that the actor interacting with it implements the BPI_PlayerKeys interface.
The door should change its color to match the key that it accepts, meaning it needs to know what Key Type can unlock it. Last, it needs the same KeyMap variable with red, yellow, and blue color combinations.
Create Variables for Interacting with the Player and Keys
To add new variables to the BP_DoorFrame blueprint, follow these steps
Go to the Content Browser, navigate to the LevelPrototyping > Interactable > Door folder, and open the
BP_DoorFrameblueprint.In the My Blueprint panel, in the Variables section, add a new variable named UseKey, with the type Boolean. This determines if the door needs a key to open it.
Create another variable named RequiredKey of the type Enum Key Type. This determines the key required to open the door.
Click the Eye icon next to both variables so the eye is open, making them editable.
Select the UseKey variable. In the Details panel, enter
Setupas its Category.Select RequiredKey and change its Category to Setup.
Create a new variable named Other Actor of the type Actor > Object Reference. This stores the actor interacting with the door and you'll use it to check if the player has overlapped with the door volume.
Build the Key Map Variable
Just like you did in BP_Key, you’ll add the map variable that maps key types to material colors. However, with the door, you don’t want the door meshes to change shape, so you won’t add new mesh shapes to the map.
To build the door’s KeyMap variable, follow these steps:
Create a variable named KeyMap, of the type Enum Key Type.
Click this variable, and in the Details panel, click the Container dropdown and select Map.
Change the map’s value type to Struct Key Data.
Compile the blueprint to add KeyMap values.
Under the map’s Default Value section, Add (+) 3 new elements to the Key Map.
When you add the first entry, change the type to another color so you can keep adding new entries, you can’t add the same entry more than once.
For each map element, add the corresponding Key Material:
M_BasicColor_YellowM_BasicColor_RedM_BasicColor_Blue
For each element, ensure the Key Mesh says None. To remove a mesh, click the dropdown and select Clear at the top of the list.
Save and Compile the door blueprint.
Add Color-Changing Blueprint Logic
With your variables set up, you can add the color-changing functionality by modifying the blueprint graph.
First, you need to change the door to have red, blue, and yellow color options that are controlled by the new RequiredKey variable you added. The door should change its color as you set it up in the level, not when the gameplay starts. Therefore, you will use the Construction Script tab to create this functionality.
To add the door’s color options, follow these steps:
Navigate to the door’s Construction Script tab, where you can create functionality for when the door is created. In the graph, find the purple Construction Script node that starts off the logic in this function.
On the Sequence node that’s connected to the Construction Script, use Add pin (+) to create one more pin, named Then 2, which you can use to build upon the chain.
The Sequence node is used to build a sequence of actions, where Then 0 gets executed first, Then 1 after that, and so on, depending on how many pins you choose to add. They help organize your graph and prevent one chain of logic from getting too long.
Drag the Then 2 pin to an empty part of the graph and create a Branch node.
Drag the Condition pin of the Branch node and create a Get Use Key node. Now, the Branch tests if the door should use keys or not.
Drag the True pin of the Branch node and create a Fn BPLSet Key node. This is the library function that applies a new material color (and mesh, if provided) to an array of static meshes.
Drag the Fn BPLSet Key node’s Static Mesh Array pin and create a Make Array node.
Click the Add pin (+) button on the Make Array node.
From the Make Array node, drag the first pin, [0], and create a Get Door node.
If you look in the Variables > Components list in the My Blueprint panel, you’ll see the door has Door and Door2 static mesh components. These are what you want to change color.
Drag the second pin, [1], and create a Get Door 2 node. This makes an array based on the two static mesh components, Door and Door 2.
From the Fn BPLSet Key node, drag the Key Map pin and create a Get Key Map node. This is a reference to the door’s KeyMap variable.
Then, drag the Key pin and create a Get Required Key node, which is a reference to the RequiredKey variable you added earlier.
Compile and Save the blueprint.
The door’s Construction Script should now have the following after the Then 3 pin of the Sequence node:
Here's a copyable version of this logic:
If copying and pasting this snippet into BP_DoorFrame’s Construction Script, you’ll need to add a third pin to the existing Sequence node and then connect that pin to the Branch node’s exec pin.
Test the Door Colors
After color-coding the door game object, you can set the doors to not open unless the player has the correct key.
In your level, select one of your BP_DoorFrame instances.
In the Details panel, enter Key in the search field at the top. This reveals two options: Use Key and Required Key. Change the Required Key to a different key type. The door’s color should change to match the key type.
If you toggle Use Key to false, the door’s color won’t update, since you set that as a condition in the blueprint.
As a reminder, this is the benefit of using the Construction Script graph tab in the Blueprint Editor. You can see changes happen in the level editor instead of having to wait to enter game mode.
Build Key-Based Door Logic
Next, you can build the functionality to check what keys the player has. For this, you will define a custom function named fnHasKey in the BP_DoorFrame blueprint that checks if the player has the required key.
A function is a reusable set of blueprint nodes that performs a specific task.
Create a Function That Checks for Keys
This function will compare the door's required key with the player character's array of keys and return a true or false (boolean) value. You'll use a local variable for that boolean return value.
To create a function with a local variable, follow these steps:
In the
BP_DoorFrameblueprint, in the My Blueprint panel, use Add (+) next to the Functions section. This is similar to adding a variable, but instead, you’re adding a function.Name the new function fnHasKey.
Since a function can have its own set of nodes, it opens in its own fnHasKey tab with a separate node graph. If you close this tab and need to re-open it, double-click the function in the Functions list.
In the My Blueprint panel, you will see a new section at the bottom that’s called Local Variables (FnHasKey). Create a new Local Variable using Add (+) next to that section.
Name the variable HasRequiredKey and set its type to Boolean.
Local variables are similar to regular variables, but local to a particular function. They are useful for storing temporary values while the function runs. You can then pass this value back to the rest of the blueprint by using a Return Node.
With the function set up, you can add logic that checks if the player has the right key.
To check if the actor in the door’s volume has the required key, follow these steps:
Drag the pin of the fnHasKey function entry node and create a Sequence node. This organizes the function’s logic into a sequence of actions that run in order.
Drag the Then 0 pin of the Sequence node and create an Fn BPIGet Keys (Message) node. This is the interface function that returns an array of keys the player has already found.
Drag the Target pin of the Fn BPIGet Keys node and create a Get Other Actor node. Once you set up the door’s event graph, this variable will store the actor overlapping the door’s volume.
Drag the HasRequiredKey local variable near the Fn BPIGet Keys node and select Set.
Drag the Exec pin of the FN BPIGet Keys node and connect it to the Set HasRequiredKey node.
From the Set HasRequiredKey node, drag the HasRequiredKey pin and create a Contains Item node, listed under the Array section of the search. This node checks if a specific item is in an array and returns true or false.
You can also search for Array Contains Item to narrow down the search to that particular option.
From the Contains Item node, drag the Target Array pin (the square pin) and connect it to the Held Keys pin of the Fn BPIGet Keys node.
Drag the Item to Find pin (that looks like a circle) of the Contains Item node, and create a Get Required Key node.
This is what your function’s graph should look like so far:
This sequence of actions checks if the keys held by the OtherActor (variable) contain the RequiredKey (variable). If so, it will set HasRequiredKey to true.
Now, pass the HasRequiredKey result to the rest of the blueprint. To do this, use a Return node, which stops the execution of a function and returns a value to the blueprint that called the function.
To end the function with a Return node, follow these steps:
From the Sequence node, drag the Then 1 pin, search for Return in the node actions list, and select Add Return Node.
To make the function return a value, it needs an output. Click the Return Node to highlight it.
In the Details panel, use Add (+) next to the Outputs section at the bottom. This adds a new output, which is the value it passes out of this function.
Name this output KeyFound and change its type to Boolean.
Back in the graph, drag the Key Found pin of the Return node, and create a Get HasRequiredKey node.
The complete FnHasKey function graph should now look like the following:
If you copy this snippet into your project, you need to connect the FnHasKey function entry node to the Sequence node.
Lock and Unlock Doors With Keys
Now you can modify the door to open if all the necessary conditions are true.
Just like with the key, you’ll need to check if the character implements the BPI_PlayerKeys interface (the player’s “permission slip”) before they can try to open a door that uses keys.
So before it opens, the door must check for the following conditions:
The door is set up to use keys (UseKey = True).
The overlapping actor is the player (it implements BPI_PlayerKeys).
The player has the required key type.
To test if the actor interacting with the door is the player, follow these steps:
In
BP_DoorFrame’s Event Graph, find the Event ActorBeginOverlap node. This collection of nodes controls what happens when a character steps into the door’s collision volume. You’ll add a blueprint interface and key requirement to this logic so the door won’t open unless the actor is the player and they have the right key.You can use Ctrl + F to search for the name of a node. Click on the search result to go directly to it.
Disconnect the Event ActorBeginOverlap node from the Door Control node by holding Alt and clicking the wire between the two nodes. Move the Event node back so you have space for more node actions before the Door Control.
Disconnect Blueprint NodesFrom the Event ActorBeginOverlap node, drag its pin and add a Set Other Actor node. Connect the Other Actor pin of the Event node to the Other Actor pin of the Set node.
This stores the actor that overlapped with the door area.
From the Set Other Actor node, drag the blue Value pin and create a Does Object Implement Interface node. Set the Interface value to
BPI_PlayerKeys.From the Set Other Actor node, drag the Exec pin and create a new Branch node.
To check that the door uses keys, follow these steps:
Drag the True pin of the Branch node and create an Fn Has Key node, which is the function that you created earlier in this tutorial. It takes the key type required to open the door and checks the player’s Held Keys array for that key type. Calling this function here will execute the nodes in it.
From the Fn Has Key node, drag the Exec pin and create a new Branch node.
Connect the Key Found pin of the Fn Has Key node to the Condition pin of the Branch node.
Connect the new Branch node’s True pin to the Door Control node’s Play pin.
So far, this logic only allows the door to open when the player has the right key. The door should also open when:
The door doesn’t require keys, or
A non-player character tries to get through the door.
The first Branch node and And node tests for both of these conditions. If either is false, the Branch is also false.
To ensure the door opens for NPCs and when keys aren’t required, follow these steps:
Connect the False pin of the first Branch node directly to the Door Control node’s Play pin. You can use connectors by double-clicking on a wire between two nodes to organize your blueprint.
Compile and Save the blueprint.
Now, when the actor does not implement the key interface, or the door does not require keys (UseKeys = False), the door still opens.
In this tutorial, we designed the doors to allow NPCs to pass through them. If you’d like your game to work differently, go ahead and try to change the graph yourself.
The new BP_DoorFrame Event Graph logic should look like the following:
Add Comments to a Blueprint
You can add comment blocks in your blueprints to create visual-only notes that group nodes together and explain what each part of the blueprint does. Comments help you and your team members know at a glance what functionality your nodes are performing and keep your blueprints organized.
When building blueprint logic, first focus on creating the functionality, and then highlight the nodes you have added and add a comment to contain and describe them.
To add a comment in a blueprint, follow these steps:
Click the graph to ensure it's the active panel.
Press C on your keyboard. This adds a comment box.
Double-click the text field at the top of the box to enter a comment.
To resize the comment, ensure the comment is selected (highlighted with a yellow outline), and drag an edge or corner.
To group notes within a comment, drag those nodes inside the bounds of the comment.
You can also select one or multiple nodes and press C to add a comment that contains the selected nodes.
Test Your Doors
Go back to your level in the Level Editor. Use your doors’ Required Key property to set them up with different colors and add a BP_Key for each color.
Now, play the game. If you walk up to the door without picking up a key, the door will not open.
But if you pick up the key, the door opens when you approach it. When you move far enough away, it’ll close automatically.
After picking up one key color, try to open a door that’s a different color. The door should stay closed.
If you're working with this tutorial's sample level, select the door that leads to Hallway 2 and change its required key to the blue key. Next, select the door that leads to Hallway 3 and change its required key to the red key. Make the door to Hallway 1 yellow.
Add Feedback with Debug Messages
If you want to check what’s happening in a blueprint during gameplay, you can use Print String nodes to display messages on screen. Unreal Engine doesn’t display these messages in a final game.
Try adding a Print String node to confirm the type of key the player has picked up.
To display a debug message with Print String nodes, follow these steps:
In the
BP_AdventureCharacterEvent Graph, go to the set of nodes that starts with Event fnBPIAddKey and adds keys to the HeldKeys array.Drag from the Add node’s Exec pin and add a Print String node.
The In String is the text that appears on-screen. Enter custom text, or connect the Event node’s Key Type pin to In String. This displays the key the player is picking up.
Compile the blueprint.
Play your game again and pick up the keys. You’ll see debug text confirming each key color as you pick them up.
When you’re done, go back to the node graph and delete the Print String and Enum to String nodes. Compile and Save the blueprint.
If something isn’t working as expected in a blueprint, you can add Print String nodes after calculations, event calls, or function calls to help track what’s happening with values and flow.
You can also open a blueprint while the game is playing, its wires light up to show the logic running in real time. This Execution Tracing is a quick way to spot what’s happening alongside your Print String messages.
Place Pickup Items
So far, you’ve been placing keys on the floor. To make this more interesting and engaging for the player, try introducing a platforming element.
In this tutorial’s sample level, we added some verticality by placing the key in a high place so the player has to jump to the key. Here, there’s a minor risk of falling and having to start over.
The player practices jumping on the first and second platforms before they are put to the test with the more difficult final jump to the pillar.
Try the Sample Level
If you’d like to add the new pieces of the room designed in this part of the tutorial series instead of creating your own, copy the snippets below.
Start Room’s Blockout
This text snippet contains the ramp, recessed floor, column, and two platform meshes added to create the path to the yellow key.
Begin Map
Begin Level
Begin Actor Class=/Script/Engine.StaticMeshActor Name=Floor_168 Archetype="/Script/Engine.StaticMeshActor'/Script/Engine.Default__StaticMeshActor'" ExportPath="/Script/Engine.StaticMeshActor'/Game/AdventureGame/Designer/Lvl_Adventure.Lvl_Adventure:PersistentLevel.Floor_168'"
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.Floor_168.StaticMeshComponent0'"
End Object
Begin Object Name="StaticMeshComponent0" ExportPath="/Script/Engine.StaticMeshComponent'/Game/AdventureGame/Designer/Lvl_Adventure.Lvl_Adventure:PersistentLevel.Floor_168.StaticMeshComponent0'"
StaticMesh="/Script/Engine.StaticMesh'/Engine/MapTemplates/SM_Template_Map_Floor.SM_Template_Map_Floor'"
bUseDefaultCollision=False
StaticMeshDerivedDataKey="STATICMESH_34081786561B425A9523C94540EA599D_359a029847e84730ba516769d0f19427Simplygon_5_5_2156_18f808c3cf724e5a994f57de5c83cc4b_680318F3495BDBDEBE4C11B39CD497CE000000000100000001000000000000000000803F0000803F00000000000000000000344203030300000000"
MaterialStreamingRelativeBoxes(0)=4294901760
To Start Room’s new blockout shapes, follow these steps:
In Unreal Editor, remove all keys from Start Room so they don’t get lost in the new geometry.
Click Copy Full Snippet.
In Unreal Editor, ensure the viewport is the active panel (click anywhere in the viewport or Outliner and press Esc), and then press Ctrl + V.
If you moved any of the blockout rooms from the previous part of this tutorial, the new meshes may not appear in the right place. Move them as needed.
Three floor pieces are covering the new recessed floor. In the viewport, click each and press Delete.
Sample Copy Paste Demo
Next Up
Your player character can pick up keys, but there’s no feedback to tell them what they have picked up so far. In the next section, you’ll create a heads-up display (HUD) for the player that shows them the keys in their inventory.