6. Doors & Keys

In this part, we'll implement the new challenge in level 2: opening a door with a key. Start by opening the level 2 scene, which already contains the setup and prefabs.

1. Add a HasKey variable

When the player reaches a door, we'll need to check if they have a key. For this purpose, we'll use a boolean (true / false) variable on the player.

  1. Select the Player object
  2. Add a new boolean object variable called HasKey, default to false
  3. Apply the changes to the prefab so other players share this variable


2. Create the key flow machine

When the player collides with the key in the scene, the HasKey variable should become true, and the key should disappear. 

  1. Select the Key object
  2. Add a new flow machine
  3. Create a new macro for it called Key
  4. Apply the changes to the prefab

The graph is really simple now that we can reuse our On Collision With macro:


Destroy is located under Codebase > Unity Engine > Game Object. It's important to note that unlike most functions, this one does not automatically take Self as its target, which is why we must explicitly connect a Self unit.

3. Create the door flow machine

Here we go again:

  1. Select the Door object
  2. Add a new flow machine
  3. Create a new macro for it called Door
  4. Apply the changes to the prefab

In the graph, we'll check the HasKey variable on the player. If the key is found, we disable the box collider on the door and change its sprite to look open. If the key is missing, we just output a message to the console for debug.

  • Set Enabled is located under Codebase > Unity Engine > Box Collider 2D
  • Set Sprite is located under Codebase > Unity Engine > Sprite Renderer
  • Log is located under Codebase > Unity Engine > Debug

If you test your game now, the door should open only if you've grabbed the key:


4. Display the key in the HUD

The last thing we have to do is to handle the HUD display for the key. 

When the player grabs the key, the empty key icon should become filled.

If there is no key in the scene, the key icon should be hidden altogether.

  1. Open the HUD scene
  2. Select the Key object under HUD > Row
  3. Add a new flow machine
  4. Switch its source to Embed

We switch the machine's source to Embed because we will only ever use this graph once, in the HUD scene. In other words, there is no need to create a reusable macro because the HUD is not a prefab. You can learn more about machine sources and prefab restrictions in the manual here.

To hide the key icon if no key exists in the scene, we can set the game object to inactive if there are no game objects tagged with Key:

  • Find With Tag and Set Active are located under Codebase > Unity Engine > Game Object
  • Null Check is located under Nulls

To change the sprite depending on whether or not the player has the key, we need to check the HasKey variable on the Player object:

You can find the sprites HudKeyFull and HudKeyEmpty under Sprites / HUD.

There is a small performance problem with our graph: Find With Tag is known to be a bit slow. It's not an issue if we only use it once on Start, but since we're calling it every frame in Update, it would be ideal to use a faster way to find the player. This is slightly premature optimization (our game would run perfectly fine with Find With Tag), but we'll show it for the sake of teaching "best practices".

We'll use a application variable called Player and holds a reference to the player game object. It will get automatically created by the player graph, so we won't need to set it up in every level manually. This is a simple implementation of the "singleton" pattern: because we know there's always only 1 player in the game, it's safe to assign its instance to an application variable.

  1. Save the HUD scene
  2. Open the PlayerController flow macro
  3. Add this group of units somewhere in your graph:

Now that this is done, we can go back to our HUD key graph and replace Find With Tag by Get Application Variable:

That's it! Now, if you test your game, you should see the key sprite change in the HUD:

This article was helpful for 22 people. Is this article helpful for you?

In step 4, HUD key's scripts are there, tutorial maker forgot to del them :D

+1

I think I fixed this now!

+2

Wouldn't it be better not to run update sprite graph every update, but fire an custom event when we collide with the key?

+3

A little bit yes! But because this game is not at all performance intensive the tutorial opted for simplicity over optimization. There are multiple ways of doing any task in Bolt, and an event would work as well.

Just one thing, when you open the door the key sprite remains full. Shouldn't it be the "keyempty" again or even disable the object? (like when you check if there is any key available in the scene)..

+2

Well, in that case, there's only one door and key, so HasKey doesn't get reset when you go through the door. You could modify the door script to set HasKey to false after opening it if you wanted the 1 key = 1 door logic!

Alright! Thanks Lazlo!

For me I made HasKey an App Variable  went back over all Items and change the Get Variable  to Get App Variable  once done on the Key Door & Player all worked but have now you have to reset that when you change levels  ;)

Ok. On the latest version.

So sorry I am missing something. Does both the Player and HasKey both now a 'Application' type or is one left as a Object. But ether case, when you hook one to the next and then to the Select it removes the HasKey value.

Don't worry. I see what I was doing wrong. So when we do a Start>Get Variable on the Player to get itself. And then on another object we do a Get Variable> Player. Is this a By Val to the object. That is we change this anywhere it will change for all that do a Get Variable or is it a ByRef (snapshot at the time we do a Get Variable) when then grab values from the GameObject after we Get Variable Applications>Player

So  iapplication variables are global variables? Is there any other way to access a variable on another object/ flow machine? Somehow helping to split up graphs?

Yes, they are! You can access variables on any other object with the Get Object Variable unit, as long as you specify a target (it is Self by default, but it can be anything else). Likewise, you can use Scene variables for anything in the same scene.

The only type of variable that is local and cannot be used from outside are the Graph variables.

Seems like this page is not up to date, it doesn't work and the update note at the end is confusing. Could you redo this part of the tutorial so it can be followed without errors and confusion? I'd love to continue.

Updating now, sorry for the huge delay on this!

Are you  sending your node into the HasKey( get variable) string? And not the game object? Beginner here so I’m blindly trying to help. I do it all the time as well.  Read the error from the graph inspector instead of the console, might be more helpful to fix the issue.

I don't know, it's all so confusing to me. Now I fixed that error somehow, but my Death group is not reloading the level when I fall on the spikes. I think it will just take some time for me to get over the learning curve, as I just started using Bolt 2 days ago. Thanks for answering.

I've got a super annoying little bug.  I have the HasKey variable set to an App Variable (I'm guessing this is their idea of "Globals") and the Sprite animation updates, but the collider for the Door is still in place and my Player character cannot walk through the door.  Any solutions?

Not sure if you figured this out yet or not, but while running your scene with the inspector on the Door, check to ensure that when the player collides with the door, the sprite renderer changes to DoorOpen and the Box Collider 2D component switches off.  If these actions are missing from the Inspector, then there is an issue with the Door's Flow Machine.  

Ensure that these nodes are included and working in the flow machine while running the scene.  I'm currently working through the tutorial, so if this doesn't work, let me know.


Thanks Ian, I was working through the tutorials 4 weeks ago and I got stuck here, so I kinda gave up on Bolt. I'll try it again tonight and hopefully I can get over this hurdle. This page in the tutorials seems very unclear and it lost me.

@Lazio Is it possible in Bolt to copy all of the player's variables & data during scene load? 

I understand that the proper use here is for Application Variables, but just out of curiosity - what would it take to iterate & copy variables (their name, type, value) from one object to another?

+1

I went a slightly different route because you mentioned "Find Game With Tag" is slow, and there's no reason why we should keep looping through the Update to check for something that we can easily check when we need to. 

I'm not sure if the way I did this is "cheating", "bad practice", etc... But I was able to manage this by triggering a Custom Event on the Player object and then listening for the Custom Event on the Player object in the HUD Key Macro.

HUD Key Macro

save image


Item Key Macro (when the player collects the key)

save image



That's another way to do it! I went with simplicity over performance for this tutorial, but this is perfectly acceptable.

I really like the fact that you can target objects to send/receive events to.

+2

Hi ! Thank you for this tutorial.

I think there is a mistake for this part : 


The variable is not "Key" but "HasKey" : 


Thank you again !