Every game needs user interaction. Without interaction, games lack their most powerful ingredient – player choice. In this tutorial, we will start to add more interactivity to our games using an event-driven system.
In the context of a game, an Event could be anything that changes in the game world. It could be the user pressing a button on their gamepad, a countdown timer reaching zero, or two enemies colliding. There are three main types of Event :
- User interface – the user has interacted with something in some way.
- Timer – a timer has reached a value.
- System – an embedded system (such as the physics engine) has fired an event.
When an Event occurs in our game, we can use that event to cause a reaction. This tutorial will be focusing on adding functionality to our game that causes a response to an Event, and changes the state of the game.
Introduction To Puzzle Games
Puzzle games can be as elaborate and exciting as you like. They can be made more complicated by giving obscure clues and adding layered objectives, or easier by giving more clues and reducing the number of objectives.
For example, a puzzle game could be as simple as “Open the door”, where the user just opens a door. Or it could be a bit more complicated. For example, if the door needs a key, but the key is locked in a vault, and to get in the vault you need the code which is written on the inside of a teapot which you need to smash with a hammer, but the hammer is positioned a bit too high to reach so you need a box to stand on…you get the picture.
This tutorial will guide you through making an easy puzzle game, and then add more obstacles to make it harder.
Create Your Game
Create a new Empty Game and call it “Super Smash-n-Grab”.
When you enter the game, select the option to Open Asset Library.
Navigate to the Community tab. Find and install the Package “Smash-n-Grab Tutorial”. If you have any difficulties with this step, revisit the Packages tutorial to get a rundown on installing Packages in Crayta.
The Smash-n-Grab Tutorial (working) Package gives you everything you need to make a simple heist-themed puzzle game.
First you need to add your bank vault. Switch back to the Library and navigate to the Templates tab and highlight the Bank Vault Template.
Add the Bank Vault Template to your Hotbar.
Close the Library and add an instance of the bank vault Template to your world. Find a good location and place it. Then navigate to an empty Hotbar slot to make it easier to navigate the scene.
Gaining Entry: Using the Keypad
By default, the door of the Bank Vault is locked. Before we Preview the game we need to unlock the door and then link the keypad to the door to be able to open it.
Start by looking at the door, and open the Entity Editor. If you navigate to the bottom of the Entity Editor you can find the Script: LockedDoor Properties.
Aha here is the first problem. You can see that the “locked” Property is checked, which means the door is currently locked. Uncheck the locked checkbox.
Press the button highlighted in the top-right to allow you to preview your game.
Interact with the keypad next to the door by looking at it and pressing the interact key. The door should swing open.
Seems pretty easy to get in the bank vault, right? This is because the door is unlocked by default. Let’s turn up the difficulty of this puzzle game. Now return to the game editor.
Securing the vault
In Edit mode, look at the door and select the option to Edit ‘BankVault-VaultDoor’ to enter Entity Editor.
Make sure you are editing the door by checking the name at the top of the Entity Editor – it should be “BankVault-VaultDoor”. Return the Locked Checkbox to its Locked state.
You have just created a puzzle. Now we need to give the player a way to solve it!
Gaining Entry: Detonation
This tutorial will cover blowing open the door with TNT first, and then using a key to open a different door.
Creative Control: Player Choice
Games like Hitman and Metal Gear Solid strive to have multiple solutions to each problem. Giving your player choice forces them to decide, makes the journey more interesting and makes the game feel less linear.
Jam some other ideas on other ways to get past a door. For example, you could use the voxel tools to create a hidden tunnel under the vault, or add a keycard that unlocks the keypad, or you could blow the door open with TNT! The only limit is your imagination (and, let’s face it, physics.)
Open the Library and navigate to Templates.
Switch to an empty slot on your Hotbar and add the TNT Template to your Hotbar.
Place the TNT on the door of your bank vault.
Open the Entity Editor for the TNT and change the position and rotation Properties to fine tune the position of the TNT. It should be flat against the door.
Open the Library again and open the meshes tab. Add the TNT Plunger to your Hotbar.
Place the TNT Plunger nearby, so you can see the door when you press the plunger.
Preview your game and make further adjustments as required.
If you try interacting with the plunger in Preview mode you will find that nothing happens. This is because we haven’t told the TNT Plunger to listen to any events yet. We need to tell the TNT Plunger what to do when the user interacts with it, otherwise nothing happens. Return to edit mode and we will do just that.
Tech Tip: Events Terminology
Listening, triggering, handling…these are terms used by game developers to discuss Event systems. Using the correct names is super useful when you need to communicate your vision to other members of your game development team.
Event trigger/ Event fire: When an event occurs, we say that the event has “fired”. The thing that caused the event to fire is called the “trigger”.
Event handler: The code that is executed due to an Event being fired is called an “Event handler”.
Event listener: An event listener links an Event Handler to an Event. In some game engines we would need to write this in manually, but Crayta manages our Event listeners for us.
In edit mode, look at the TNT Plunger and select the option to Edit ‘TNTPlunger1‘ to enter the Entity Editor.
Navigate to the bottom of the Entity Editor to find the On Interact Property.
Crayta Entities automatically listen out for events that might affect their state in the Game World, such as colliding with another Entity or the player interacting with an it. You can make things happen by adding functions to the event property boxes.
There are 2 possible events that we can listen for on the TNT Plunger:
- onInteract: The player looks at this entity and presses the interact key.
- onCollision: The player’s character touches this entity
Tech Tip: Functions
A function is a chunk of code with a single identifier. Programmers group chunks of code into functions so that they can be re-used easily, and to help organise the code into a logical pattern. A single script can have multiple functions.
A function identifier will usually describe the intention of the code within the function. For example, a function with the identifier “makeInvisible()” should make an entity disappear, a function with the identifier “explode()” should make an entity explode. To run a function, we “call” it.
For example, here is the function within the LockedDoor script which “destroys” the door:
self:GetEntity().collisionEnabled = false self:GetEntity().visible = false
If you read the code above, it states “for the entity this is attached to, make collisionEnabled false and visible false”. What this means, is that the collisions are disabled and it is made invisible. This is a simplified way of removing an entity from the game. It’s not the most optimal way, but completely destroying an entity comes with other programming responsibilities that are beyond the scope of this tutorial.
To setup the event highlight the “+” next to onInteract and select it. Now, highlight the box with the placeholder “(…)” and select it again.
You will see three new property boxes appear; Entity, Script and Event. We will use these properties to target a specific entity, target a script attached to that entity, and choose a function within that script.
Highlight the Entity field and select it. This will display a list of every entity in your scene.
Tech Tip: Parents and Children
An Entity in Crayta could be a Mesh, a Voxel Mesh, a Sound or any other item that is added to your game.
When you add an Entity to your game, Crayta will make it a “Child” of another Entity so that it is attached to something in your game.
For example, a table is added to the game. Then a cup is placed on that table. Because the cup is on the table, Crayta will add the cup as a child of the table. Then, if we move or rotate the table, the cup will move or rotate with it.
Parent/child relationships exist in most game engines, and are shown using lists:
When we added our TNT to the door, Crayta renamed it to tNT1, so that we can distinguish between that specific TNT, and any other ones we might add to our game later on.
With the drop-down expanded for the Entity field; highlight the Terrain Entity. Expand the list of children added to the Terrain Entity. Do the same with BankVault and you should see BankVault-VaultDoor. Continue expanding the lists to find tNT1. You may find that the tNT1 appears in a slightly different location in your tree view:
World > terrain > bankVault1 > BankVault-VaultDoor > tNT1
Highlight tNT1 and select it so it appears next to the word Entity in the properties panel.
Our TNT only has one script attached to it, so the Script Property is automatically filled with our tntDetonator script. If there was more than one, we could use this box to determine the exact script.
Finally, highlight the arrow next to Event and select it. You will be given the choice of two functions that exist in the tntDetonater Script; Detonate() and Init(). Select Detonate().
Now close the Entity Editor. You have now hooked up the TNT Plunger to run the Detonate() function on the TNT that is attached to the bank vault door.
Preview your game.
During the game Preview, interact with the TNT Plunger by looking at it and pressing the interact key. You will notice that the TNT detonates, as expected, but the door to our bank vault remains firmly locked. We can fix that by adding another Event Listener onto the TNT Plunger’s onInteract Event.
Return to Edit mode, open the Entity Editor for the TNT Plunger once again. Navigate down the Properties and press the “+” next to On Interact, underneath the previous function we added. Using the same method that we used when adding the Detonate function, add the following function:
- Entity: bankVaultDoor
- Script: LockedDoor
- Event: DestroyDoor()
You should now see two items in the onInteract field; tNT1 / tntDetonator and BankVault-VaultDoor / LockedDoor.
Preview your game again and interact with the TNT plunger. You should find that the TNT explodes, and the door is destroyed. ACCESS GRANTED.
We can add as many functions as we like to this event listener, or to the other event listeners. If you choose to program your own functions you can use this Event Property to make them run.
Gaining Entry: Unlocking The Door
So far we have a bank vault where players can gain entry through the use of explosives. Great! What happens next? Well, usually once you have got the goods you need to escape without getting caught. We are going to add an outer door as an extra obstacle to get in the way of the player reaching the vault.
Add a different door Mesh to your hotbar and add it to the Game World.
You may want to use the Voxel tools and remove a suitable space in the bank wall, otherwise it will open into a brick wall! Now your player will have to gain entry into the bank first, then the vault and then escape out of the building.
Creative Control: What’s Your Game About?
This tutorial covers adding two doors, but you can use the same techniques to add more doors, change the scenario and change the direction of the game.
For example, the player could start in a dungeon and have to escape a castle, or rescue someone from a prison. Requiring obstacles to be solved in different ways keeps your players guessing and makes the game more interesting. Get creative!
Don’t forget you can change the Mesh Asset Property of a Template. So you could change the bank vault door to a jail cell door, or a door to a townhouse.
In Edit mode, open the Library and add the Keycard Template to your hotbar. Then close the Library.
Place the keycard in your game world. Preview your game and adjust the position of the Keycard using the Entity Editor if necessary.
You could place your keycard somewhere obvious, or you could place it somewhere devious. You could also consider where someone might leave a keycard by accident, such as on a table (look in the Meshes tab in the Library for inspiration). If you’re more of the trickster type, be sure to give your player clues so that they don’t get frustrated!
Return to Edit mode and open the Entity Editor for the Keycard.
At the bottom of the Entity Editor you will find a script attached to this Entity; HideShowScript. The next step in this tutorial will show you how to use the Event Properties to unlock the door and make the keycard disappear, simulating that you have picked it up.
Add the following to the Keycard’s onInteract Event Property:
Preview your game and interact with your keyCard. You will find that it disappears, simulating that you have “Picked it up”.
Return to Edit mode.
To make the outer door unlock, you will need to add a Script to it. The Script is the same Script used on the bank vault door.
Open the Entity Editor for the outer door.
At the bottom of the Entity Editor click the Add to Entity button. Select Add > Script > LockedDoor and add the LockedDoor Script to this door.
Check the locked checkbox to ensure that the door starts locked.
Click the + on the On Interact and choose the Door instance > LockedDoor > ToggleOpen(). This will mean when you interact with the door it will open, but only if it’s unlocked.
Unlocking the door is the last piece of this puzzle.
Open the Entity Editor for the Keycard once again.
Return to the onInteract field. This time we will also add the unlock function to the onInteract event. Select the following:
- Entity: outer door (make sure to select the right door here)
- Script: LockedDoor
- Event: UnlockDoor()
Close the Entity Editor for the Keycard. You have created a way to pick up the key and unlock the door.
Preview your game. Interact with the Keycard and you should find it disappears (and behind the scenes we know the door has unlocked). Then, interact with the outer door and the door should swing open.
Tech Tip: Testing
Testing is a vital part of making games as it ensures that the game you have made is doing what you expect it to do.
Most of the time, developers test the game as they develop new features, but sometimes adding a new feature, or changing a part of the gameplay, may cause unexpected or unwanted things to happen to other parts of the game. Unwanted behaviour in a game is called a “bug” and needs to be fixed before continuing with the game development.
For example, in our situation, selecting the wrong door to “open” when the player interacts with the keycardReader might cause the vault door to open, rather than the exit. This would be very confusing to the player, and they won’t be able to get out!
Test your game regularly to make sure your game is doing what you want it to do, and make sure to fix any problems when they come up.
Congratulations, you have created a bank heist game. In this tutorial you have looked at:
- What are Events and how do we use them
- Using the Event Properties to add interactivity to the game
- Changing a mesh and adding more interactivity to craft new puzzles
How did you get on? If there were moments which didn’t work how you wanted, now is a good time to revisit your game and fine-tune it, and practice what you have discovered in this tutorial.
If you want to carry on adding to this game, here are some ideas that you can explore using the techniques we have looked at in this tutorial:
- Hide the keycard in the bank vault itself, so that the player has to get in the bank vault before they can leave
- Give your player the choice to either blow up the vault door, or use a keycard hidden somewhere else in your game
- Create another obstacle, where the player has to pick up some TNT before it appears outside the bank vault door.
- Make a dungeon “escape room” by linking multiple obstacles that need to be solved before the player can escape
Next Up: UI
The next tutorial will look at how we can display information to your players using the inbuilt UI system. This will allow you to add written narrative elements and dialog, show player health or points, and show the player a win or lose message.
Combining communication with events will enable you to create completely unique and exciting narratives that reward and challenge your players.