Categories
Basic Tutorials

Obstacle Game Mini-series #5: Finishing Touches

Polish is one of the most crucial parts of making a great game. This is the last tutorial in the Obstacle Game Miniseries, and in this one you will explore how to theme your level, clean up unnecessary items and add some beautiful architecture and landscapes to make your world feel vibrant and alive.

Firstly, use the Drone to remove the old level completely from the level. An easy way to do this is to use the Extrude tool to lower the original route into nothingness.

Delete the “death” objects by using the Select tool to select them (RT) and then press LT to delete them completely.

Themeing Your Level

Now to theme the level in a Tech Noir style. There are many neon Props and Voxels within the Crayta Library, and you can use these to give highlights and interesting visuals to your level. 

For inspiration, consider some of Tech Noir classic films such as Terminator, Alien and Blade Runner. Look for the use of Neon lights and the textures and colours that are prevalent throughout. 

Creative Control: Adding FlairThe great thing about building games is that you can express a thought, an experience or a story that you want to share with your Players. Use the theme of your level to explore some of your own ideas. Imagine new worlds and don’t be afraid to try out new things and imaginative combinations.

Return to the start. You can use a signifier here to give the Player an understanding of what to do, and to make the world feel more realistic. 

Open the Library, and add the Chevrons Arrow C Prop to your Hotbar.

Place it on the wall next to the Elevator.

Use the Library to explore some additional Props that might fit within a high-tech office building. For example, behind the Player I have added a futuristic Cafe Door and Keypad.

These items tell the Player a story, showing that their Character has come from somewhere, and not just arrived in the game.

You can use strip lights to lead the Player in the right direction, and Vending Machines make the world feel lived in. You would normally have Vending Machines by an elevator so that people can snack whilst they wait (people still snack in a Tech Noir future right?).

Moving outside the Player is running along what seems to be suspended platforms in the sky. Whilst this is an interesting concept, it doesn’t really work with the theme.

To fix this, edit the Voxel Mesh so that it feels more like a superstructure from the future and add some Props to give it life.

This blank wall above the Elevator can host some neon-art.

Roof related Props can be put in clumps to make the roof feel more “roofy”.

Searchlights start to build the picture of a secure building.

The secure building narrative is further emphasised by barbed wire on the edges of a first floor roof.

There was a large unused space at the bottom. A good way to fill this was to create a small scene like a monorail station.

It doesn’t need lots of detail, as the Player will never see this closeup, but it’s worth adding a couple of small touches so that it feels alive.

Tech Tip: OptimisationWhen you add Props that the Player will never touch or interact with, it is worth making sure that they are not impacting the games performance. Open the Entity Editor for these Props and uncheck collisionEnabled.This stops the physics engine from calculating the collision mathematics for these Entities 60 times per second (or more), meaning that it can spend more time in giving the Player a great experience.

The rooftop pathway is also a good opportunity to add some neon. This first part is supposed to be very easy, so highlighting the edges is helpful to the Player.

The scenario for the Vault Door scenario needs some work to make it feel more realistic. 

The floor switch for the Vault Door sticks out because it doesn’t seem like a necessary aspect of the building. Add a fence at the corner transition to the narrower pathway and make this feel like a different part of the roof – somewhere that enables technicians access to the power and lights for the greenhouse. 

Try building a Voxel platform and adding some more Props to add drama to the situation. Lighting Props and Neon Voxels look great here both when the player is on the rooftop pathway and from a distance when they are riding on the flying cars.

The neon strips that run down the shaft add a real sense of depth inside the shaft.

Within the greenhouse, you can amp up the difficulty a little bit. Add more Saw Blades with rotateAndMove Scripts attached, and add another Statue (Cemetery) but without the PyroDetonator. The Statue (Cemetery)’s gives a solid aesthetic to this section – gothic elements work well in this theme, and the large greenhouse keeps the feeling futuristic. Additionally, the second Statue (Cemetery) Prop without the detonator makes this section slightly more difficult also.

You can also uplight the Statue (Cemetery)’s with a Light from the Primitive tab in the Library. Change their colour in the Entity Editor to make them shine green, giving an ethereal glow to this area. Change the pathway to be a solid green neon Voxel to further cement the palette for this unique area.

The flying cars currently appear from nowhere, and seemingly disappear into thin air when they have completed their journey. Let’s remedy that.

Create a new Voxel Mesh called CarTunnel and add it behind the Flying Car Prop.

Use the Voxel tools to build a tunnel for this car to appear from.

Change the inside of the tunnel to be a dark Voxel that soaks up the ambient light, such as a black Plastic (Dull).

Use the Entity Editor to move the Voxel Mesh so that it is in front of the Flying Car Prop. This will make it seem like the car is emerging from the darkness of the tunnel.

Adjust the dimensions and dress the tunnel so that it fits the theme.

Make duplicates of the CarTunnel Voxel Mesh and position them so that the Flying Car Props drive from and to them on your map.

And of course dress the final Checkpoint area, which should finish the narrative for the level. For example, by adding a Blimp Prop it gives the Player the feeling their Character has made a daring escape, and hints at a world and a story larger than this level!

Adding Sound

To add that final element of polish, you can also go back through your level and add some sound effects and music.

Start by adding some Tech Noir style music to the game. Synth Wave 80s Throwback Music fits perfectly, so open the Library, navigate to the Sounds Tab and add this to your Hotbar.

Add the Sound in the game.

Open the Entity Editor for the Sound.

Uncheck the ranges checkbox.

This will ensure that the background music plays whilst the Player navigates the entire level, adding a great score for this kind of game. Turn off 3d to ensure that the music is not only located within the corridor.

For the lift sound you can add a continuous hum in this area such as Industrial_machine_hum_tonal_amb.

Open the Entity Editor for this ambient Sound. Move it so that it is in the center of the lifts movement range, and reduce the rangemin to 300 and rangefallof to 450 so that it is specifically within the proximity of the lift. This means that it will only be audible when the Player is near the Sound

Tech Tip: Rangemin and Rangefalloff

These two values can be used to determine the reach of the sound. 

Rangemin specifies how far away the sound can travel at its full volume. You will see that by changing this value, you increase or decrease the size of the sphere that represents the distances this sound will travel.

Rangefalloff specifies how quickly the sound will become inaudible once your Character has left the range of the sound.

On the roof there is a good opportunity to add some ambient noise of the world that this level exists in. Add some Wind (Medium or Heavy) Sound to your rooftop.

And use the Entity Editor to position it high above your platform.

Notice that the range sphere for the Sound only just touches the rooftop. This way you will only be able to hear the wind when you are on the roof (rather than inside the building). You should position some additional wind sounds along the platform, taking into consideration the range sphere, and ensuring the sound will not be audible from inside the corridor or the greenhouse (because this will feel unrealistic).

The next key Sound to add is the door opening for the Vault Door Prop. Open the Library and add the Mechanism_steam_switch_01 Sound to your Hotbar.

Add it to the Vault Door Prop and open the Entity Editor for the Sound. Uncheck the active checkbox.

Tech Tip: Turning Off “Active”

Sounds which have the “Active” Property ticked will play automatically when the game starts. You need to uncheck the active box if you plan to trigger the sound to play when something happens in the game, such as when a door is opened.

Open the Entity Editor for the Vault Door Prop and locate the Properties for the LockedDoor Script.

Use the dropdown menu to select the Mechanism_steam_switch_01 you added to your Vault Door Prop. This means that when the door is opened (by the Player jumping on the floor button) the door will make this sound as it opens.

Using what you have learned about sound so far, you can dress the remainder of the level using the ambient Sound and the Sound Effects from the Library. Make sure to maximise their effectiveness by using the rangemin / rangefalloff values, and you can create variety in your Sounds using the pitch and volume Properties. Add Sounds to the doors that open, add Sound effects to the Saw Blade Props and the Flying Car Props in order to make these aspects of the game come alive. Add ambient sounds within the greenhouse, and use high and medium winds across the Flying Car timed jump puzzle.

Once you are happy with your sounds, playtest your game thoroughly, and tweak any sounds that might need moving. 

Recap

In this tutorial, you took a run-of-the-mill obstacle course and gave it a huge injection of fun. Your player gets to ride on top of an elevator, drop down into a shaft, dodge saw blades, jump on flying cars and parkour their way up the side of the building. Not bad for a day’s work!

Even More Polish

Now comes the even cooler part! Adding more polish to this level and continuing to embellish the Tech Noir / Retrowave theme.

For inspiration, consider looking at visuals from Tech Noir classic films such as Terminator, Alien and Blade Runner, as well as modern homages to these, such as Kung Fury or Blood Machines. Look for the use of Neon lights and the textures and colours that are prevalent throughout, and see if you can replicate these.

To make your level really shine, it is worth investigating the Advanced Mode in order to change the world lighting and effects. You will need access to a mouse and keyboard to do this, but it will add a lot of impact to the neons.

Categories
Basic Tutorials

Obstacle Game Mini-series #3: Spinning Saws

Here we continue the Obstacle Game Miniseries by adding the third set of obstacles. If you have arrived here without visitng the previous tutorials then you might want to start from the first one, or you can just jump right in.

In this tutorial you will:

  1. Build a greenhouse
  2. Add spinning saw blades that kill the player on contact
  3. Create an exploding Prop puzzle

Building A Greenhouse

Time to ramp up the difficulty to medium. In this obstacle, you will explore adding dangerous items to the level – spinning blades – as well as pyrotechnics!

Open the Library and select the Voxels tab.

Add the Grass (Jungle) Voxel to your Hotbar.

At the end of the corridor, use the Voxel tools to build some steps leading onto a wide open platform of Grass (Jungle) Voxels.

Build a pathway across the Grass (Jungle) in the Technical Grid Voxel. To do this, start by removing a strip of Voxels.

Open the Library and add the Technical Grid Voxel to your Hotbar.

Fill the gap with the Technical Grid Voxels to create a dramatic pathway.

You might want to spend some time designing your staircase and path here, or you can return to do this later.

This pathway will lead the player to Checkpoint3 (so they know where they are supposed to go), but we are going to put something in their way.

Adding The Spinning Saw Blades

Open the Library and navigate to the Props tab. Add the Saw Blade to your Hotbar and close the Library. Place a Saw Blade parallel to your path.

Open the Entity Editor for the Saw Blade.

Select “Add to Entity” and choose Add > Script > rotateAndMoveScript.

Use the same technique as the Elevator for Obstacle 1 to make this Saw Blade move backwards and forwards. Check the “Simulate” checkbox to test it whilst remaining in the Editor. 

Change the value in the movementEnd so that the saw reaches the other end of the Grass (Jungle) Voxel floor. Change the timing to make the Saw Blade move faster ( and make it a bit more difficult)

It might be difficult to open the Entity Editor by looking at the moving saw blade. If this is the case, you can open the Entity Editor by looking at the blue shadow that remains in the place where the Saw Blade is positioned and pressing X.

Once you have configured the movementEnd values change the rotationEnd so that the saw is also rotating. Your end values should look something like these.

Make sure that bounce is checked.

Now to make it dangerous. Select “Add to Entity” again and add the deathCollisionScript.

The deathCollisionScript is used to kill the player if they touch an object (nasty). By adding it to the Saw Blade you have just made the saw blade lethal! Now that you have completed customising your deadly saw blade, uncheck simulate to stop the Saw Blade running amok whilst you continue to work on this obstacle.

Now to create a reason for the Player to get past the Saw Blade. 

Creative Control: Efficient Use Of Traps

You can be efficient in using traps and danger by requiring the Player to get past it more than once – to reach something and double-back (as we saw in the Pad (Pressure) / Vault Door situation on the rooftop. Don’t do it too many times or the Player might find it boring.

Exploding Your Way Out

In this scenario, the Player will be reaching for a button that blows a hole in the wall and allows them to proceed.

Firstly, use the Library to add a Statue (Cemetery) Prop to your Hotbar, and add it to your world on the other side of the Saw Blade from the path. This artefact will hold your detonator for the explosion.

Now use the Library to find the Giant Fans Prop. This will be the “door” that explodes.

Add the Giant Fan at the end of your pathway through the Grass (Jungle) Voxels.

Use the Entity Editor to fine-tune it’s position and rotation. Make it block the walkway. You will build the walls around it shortly.

Add the ShowHide Script to the Giant Fans Prop. It was installed with the SuperSmashNGrab Package.

To make the Giant Fans explode, you will need to download another pack from the Community.

Open the Library and navigate to the Community tab. Find the Pyro Pack and select Install.

Navigate to the Templates tab within the Library. Add the PyroCharge and PyroDetonator’s to your Hotbar and Close the Library.

Add three PyroCharges around the perimeter of the Giant Fans Prop.

Add a PyroDetonator onto the front of your Statue (Cemetery) Prop.

Open the Entity Editor for the PyroDetonator.

Change the meshAsset Property to Door Switch.

Fine-tune the position of the PyroDetonator on the Statue (Cemetery) Prop.

By clipping it inside the Statue (Cemetery) you can make it look like it’s part of the Statue.

Now to hook it all up. With the Entity Editor for the PyroDetonator still open, click the “+” next to the onInteract Property.

Select the Giant Fans, ShowHide Script and the Hide() function.

In the pyroDetonator Script Properties, press the “+” next to the “charges” Property.

Press “+” until there are three array elements.

Now use the dropdown selection boxes to select the three PyroCharges you attached to your Giant Fans.

With this much functionality added, it’s a good idea to do a midway test before continuing. Preview your game and make sure that pressing the button here blows up the charges, and removes the Giant Fans Entity.

To finish this section you will add glass walls to the area and move Checkpoint3 to the other side of the Giant Fans. 

You can choose to practice what you have learned so far to do this yourself, or continue following this guide for step-by-step instructions.

Use the Library to select the clear Glass Voxel.

Use the Voxel tools to build this area into a greenhouse by adding glass walls.

Start by building glass around the Giant Fans.

Use the Technical Grid Voxel to build a base for a glass wall around your Grass (Jungle).

Add the glass walls and a glass roof.

As you did for Checkpoint1 and Checkpoint2, locate Checkpoint3 and move it to just the other side of the Giant Fans.

Next Steps: Obstacle #4

Success! You have just added two new doors to your game. Now that you have presented your Player with a simple challenge you can start to ramp up the difficulty and move on to creating some more difficult obstacles.

Obstacle Game Mini-series #4: Flying Cars Jump Puzzle

Categories
Basic Tutorials

Obstacle Game Mini-series #2: The Locked Door

Welcome to the second tutorial in the Obstacle Game Miniseries. This is a continuation from Obstacle Game Miniseries #1, which introduces this series and guides you through building an intriguing entrance to the level.

In this tutorial you will:

  1. Add a locked door which can be opened by jumping on a floor switch
  2. Create automatic doors

Adding A Locked Hatch

The Player is on the roof, which means we can make them take an exciting drop into a new area. The obstacles in this section will use the same tools used to open doors explored in Basic Tutorial 2: Events, but in a slightly different way.

To start with, add a turn to your roof, and use the turn as an opportunity to increase the difficulty from Very Easy to Easy – the new pathway should be 6 – 10 Voxels wide.

It’s good to have areas of your level that are not too demanding. The blank space gives the player a chance to recover after a difficult challenge, and you can always add interesting visual elements when you come to dress the level later on.

Now it’s time to add a loft hatch. To do this, you will be repurposing the LockedDoor Script from the Super Smash ‘n’ Grab Package. Open the Library and enter the Community tab.

Install the SuperSmashNGrab Package.

Return to the Library and open the Props tab. Add the Vault Door to your Hotbar.

Close the Library.

Place the Vault Door Prop at the end of your rooftop pathway.

Open the Entity Editor for the Vault Door and move and rotate it so that it is lying flat attached to the end of the roof.

Use the Voxel tools to build a setting around it.

Continue your narrow rooftop path past the Vault Door. The Player will solve this puzzle by doubling back on themselves.

Creative Control: Your own path

Whilst this tutorial guides you through making a basic level structure, the details of the level are entirely up to you. You can copy this exactly, or you can make yours more or less difficult by creating more difficult pathways to navigate.

Open the Library and navigate to the Props tab. Add the Pad (Pressure) Prop to your Hotbar.

Close the Library and add the Pad (Pressure) to the end of the narrow pathway.

Open the Entity Editor for the Pad (Pressure) to fine-tune it’s position.

Position it slightly below floor level. This way the Player will run onto it seamlessly.

Adding the Pad (Pressure) at the end of this rooftop will give us a great opportunity to create a spectacular view later on!

As you did with the Vault Door, use the Voxel tools to build around it, embedding it within the roof.

That’s the positioning taken care of, now to add the functionality.

Open the Entity Editor for the Vault Door.

Select “Add to Entity”.

Select Add > Script > LockedDoor.

You can add Sounds to this later, but for now leave the LockedDoor Script Properties blank.

Close the Entity Editor for the Vault Door and open the Entity Editor for the Pad (Pressure).

Click the “+” icon next to the onCollision Property.

Click the arrow and add the bankVaultDoor as the Entity – use the menu to find it within the terrain object.

The Script should be automatically set to the LockedDoor Script attached to the Vault Door when you select the bankVaultDoor Entity.

Select the OpenDoor() function as the Event.

Close the Entity Editor and test the functionality by Previewing the game.

You should find that when you jump on the Pad (Pressure) the door opens. If it doesn’t open, make sure that you are jumping on the pad (it takes a bit of force to run the onCollision event for the Pad (Pressure)) and then double check that you have hooked up the Properties the same as above.

Stop the Preview and return to the Editor mode.

Now to add some drama to your game by building a shaft below the Vault Door so that when the player enters it they will freefall. 

Tech Tip: DeathZ

Before we give the Player a drop to the next section, it is worth highlighting a technical aspect of game development – the deathZ (also called a death plane)!


By default, the DeathZ Game Property is set to -1000. This means that if your Player’s Z-Position gets to -1000 then they will die, and they will respawn at the start. If deathZ didn’t exist, the Player would fall forever, and Crayta would be full of Players stuck infinitely falling to their deaths! 


This Property is possible to edit in Advanced Mode (if that is accessible to you). If you don’t have access to Advanced Mode, make sure that your terrain does not go below -1000 on the Z-Axis. You may need to check your shaft to ensure the Player isn’t killed by jumping in! 
If you can’t (or don’t want to) enter Advanced Mode, select the terrain Entity and move the whole terrain up, including the Players spawn Locator which you can find where the Player is spawned currently.

To build the shaft, position your Drone view underneath the Vault Door. Use the Voxel tools to build 1 Voxel wide wall around the edge of your Vault Door.

Use the Extrude tool to extend the shaft down.

At the bottom, continue three sides of your shaft to create an opening.

Add a floor to the bottom of the shaft.

Extend the floor beyond the shaft to create a pathway out of the shaft.

Adding Automatic Doors

Open the Library and navigate to the Props tab. Add the Office Door Prop to your Hotbar.

Close the Library.

Add the Office Door to the exit of the shaft.

Use the Voxel tools to build a corridor around the door.

This door marks the entry to a new area of the map, and will give some context to Checkpoint2. You will use a trigger and the LockedDoor script to make this door open automatically when the player gets near it.

Open the Library and navigate to the Primitives tab.

Add the Trigger to your Hotbar.

Add a Trigger just in front of the door.

Open the Entity Editor for the Trigger.

Change the size of the Trigger so that it is the entire area behind the door.

Open the Entity Editor for the Office Door and add the LockedDoor Script.

And now open the Entity Editor for the Trigger once again. Click on the “+” next to onTriggerEnter.

Select the Office Door Entity and the OpenDoor() function of the LockedDoor Script.

Finally you need to add Checkpoint2 to the other side of this door. Use the Voxel tools to extend the floor.

Make sure you have the Select tool enabled (press B if you still have Voxel tools). Fly your drone to find Checkpoint2 from the original level.

Press RT to pick up the Checkpoint2 (make sure to select the Checkpoint and not an individual aspect of it – again use the tool descriptions in the bottom left to check before you press RT).

Move it to the pathway on the other side of the Office Door.

Use the Entity Editor to fine-tune the position of the Checkpoint2 (remember the grid is based on multiples of 25.000).

Preview your game and test your new obstacles.

Next Steps: Obstacle #3

Success! You have just added two new doors to your game. Now that you have presented your Player with a simple challenge you can start to ramp up the difficulty and move on to creating some more difficult obstacles.

Obstacle Game Mini-series #3: Spinning Saws

Categories
Basic Tutorials

Obstacle Game Mini-series #1: The Elevator Ride

Preface

Now that you have completed the tutorials on using the Basic mode of Crayta, it’s time to put some of your new skills into practice by creating a fully featured level.

Introduction To The Miniseries

This tutorial miniseries acts as a kind of stepping stone, to ease you into developing fully featured levels using the Basic Mode in Crayta. You will go through the whole process of working on a level, from start to finish, and end with a really cool, polished feeling game without needing to touch any scripting. 

By completing this tutorial, you will see how the skills you’ve learned can be used in lots of different ways to make something that really stands out and has a completely unique feeling. You will be making a Tech Noir themed obstacle course (complete with neons, synths and flying cars).

Aspects of this tutorial assume you have some of the skills that are detailed in the Basic Mode tutorials, such as installing Packages, using the Voxel tools, changing Properties in the Entity and World Editors, and adding Scripts to Entities. If you get stuck then it might be worth looking back at some of the Basic Mode tutorials to refresh your memory.

Now that’s out of the way, let’s get making!

Create Your Game

Start by opening the CREATE menu in Crayta. You are going to build an Obstacle Course, which also doubles nicely as a puzzle game. Find the Obstacle Course game template.

Press A to select this template. Name your game Tech Noir Treachery (or choose your own name) and select an appropriate game poster. CREATE AND ENTER to get into the game.

Level Plan

Something that can be quite handy when designing a full level is to think about how you might map out the game before you add anything or make too many changes. Double tap A (jump) to enter Drone Mode and take a look at your level.

Creative Control: Checkpoints

In the Obstacle Course level template, you have 5 checkpoints. You can use these checkpoints however you like, but a good rule of thumb is to have one checkpoint for each major peril. Players respawn at the last checkpoint they passed, which is great for ensuring your players don’t get frustrated on those difficult timed-jump puzzles (more on this later).

For each of the 5 obstacles it is your job as a game designer to design a situation which presents a problem to the player. It is also your job to design a solution to that problem – no-one likes a game that is impossible to complete! 

Your obstacles will increase in difficulty, challenging the player to adapt each time. The basic level can then proceed like this:

  1. Entrance, first small puzzle (very easy difficulty)
    • [ Checkpoint 1 ]
  2. Easy obstacle
    • [ Checkpoint 2 ]
  3. Medium obstacle
    • [ Checkpoint 3 ]
  4. Hard obstacle
    • [ Checkpoint 4 ]
  5. Very hard obstacle / climax
    • [ Checkpoint 5 – end of the game ]

A Grand Entrance

At the moment you can easily walk from the start to checkpoint 1 up some steps. The entrance to the level is quite simple at the moment, but you can make this much more interesting.

Start by removing an area around the start, so that it looks like a platform heading to the steps. Drone Mode is going to be the easiest way to do this, but it’s up to you.

Delete one square.

Use the Extrude tool to remove a row of squares quickly.

Mark out the other three sides of the platform using the same technique.

Now remove the floor using the Extrude tool on the entire terrain.

You just raised the stakes!

This is a good start – a simple puzzle. Now you can start to add a bit more complexity to make it interesting. 

Creating An Elevator Ride

For the first obstacle the player will ride on top of an elevator to reach the roof.

Open the Library and find the Elevator in the Props tab.

Highlight the Elevator and press A to add the Prop to your Hotbar and close the Library.

Place the Elevator at the top of the stairs next to the platform.

Press B to deselect the Entity Placement tool. If you need to fine-tune the Elevators position, for example in the image above the Elevator is clipping the floor, open the Entity Editor for the Elevator (press X) and change the position X, Y and Z values.

Close the Entity Editor.

To make this a more believable scenario, use the Voxel tools to build walls around your start point.

By stopping the player from walking off the side of the platform you are making this first challenge very easy. Continue adding to your level by constructing an elevator shaft using the Voxel tools.

To make the Elevator move you will need to attach a Script. The Obstacle Course template comes with the RotateAndMove Package already installed, which you will use to make this Elevator move. 

Press B to exit the Voxel tools enter Select mode. Look at the Elevator and open the Entity Editor by pressing X.

Scroll to the bottom of the Entity Editor and Select “Add to Entity”. 

Select Add > Script > rotateAndMoveScript.

Check the simulate checkbox to make sure that the rotateAndMoveScript is running in the Editor mode. Notice that nothing happens, this is because you need to add values to the rotateAndMobve Script Properties before it will move.

You want the Elevator to move up, which is on the Z-Axis. Increase the movementEnd Z-Axis value. The Elevator will now start moving. Increase this value until the Elevator is travelling high enough to take the player to the roof. To view the results quicker, change the time to 2 seconds.

You may find that the Elevator is clipping the floor or the roof of your level. You might need to uncheck Simulate to move the Elevator around or edit the Voxels.

Test that you can reach the roof by riding on the Elevator. Great job!

To lead your Player to their next challenge you will need to extend your perilous rooftop pathway. The width of your roof will determine how easy this section is. As a rule of thumb:

  • 10+ Voxels wide = very easy
  • 6 – 10 = easy
  • 4 – 6 = medium
  • 2 – 4 = hard
  • 1 = very hard

The first obstacle is supposed to be very easy, so make sure your rooftop pathway is 10+ Voxels wide.

Next you need to move the Checkpoint to the end of your first obstacle. Enter Drone Mode.

Make sure you are using the Select tool (press B if you are in Voxel tools). Look at the Locator which signifies Checkpoint1. You will see that the tool descriptors in the bottom level corner change depending on what you are currently looking at.

Pick up Checkpoint1 with RT (make sure the tools state PICKUP ‘CHECKPOINT1’ before pressing RT), and move it to your roof.

Use the Entity Editor to fine-tune the position of the Checkpoint. The Voxel grid is based on multiples of 25, so make sure that the values are divisible by 25 if you want to keep the Checkpoint to the grid positioning.

Well done! You have completed the first obstacle for the players. This one starts very easy, in fact it’s more difficult to die than it is to complete it. Test out your first obstacle using the game Preview and enjoy a pleasant Elevator ride.

Next Steps: Obstacle 2

Nice work on completing the first obstacle. You’ve managed to create an exciting start to your Obstacle Course game.

You will come back to polish this section of the level once you have completed adding all the obstacles. For now, head on to the next tutorial in the Obstacle Course Miniseries – Obstacle Course Miniseries #2: The Locked Door to continue your journey.

Obstacle Game Mini-series #2: The Locked Door

Categories
Basic Tutorials

Obstacle Game Miniseries #4: Flying Cars Jump Puzzle

Continuing the Obstacle Game Miniseries, we now look at adding a jump puzzle involving flying cars!

If you have arrived here without visitng the previous tutorials then you might want to start from the first one, or you can just jump right in.

In this tutorial you will:

  1. Add Flying Cars and make them move
  2. Create a timed jump puzzle across moving cars and cranes
  3. Introduce a parkour style jump puzzle up the side of a skyscraper for the Player to complete the game!

Adding A Flying Cars Jump Puzzle

Obstacle 4 should start to really challenge the Player. It’s time to give them a bit of a thrillride.

Open the Library and add the Flying Car Prop to your Hotbar.

Add a Flying Car Entity to your level.

Use the Entity Editor to move the Flying Car Entity’s position so that it runs parallel to the end of the Checkpoint3.

Your Player is going to have to jump onto this car as it passes, just like the logs in everyone’s favourite frog-based jumping game, so make sure that the car is positioned at a distance that is jumpable from the checkpoint.

With the Entity Editor still open, press “Add to Entity” and add the rotateAndMoveScript.

Make a note of the X-Axis value of the start position (this one is 1850.00).

Now move the car backwards on only the X-Axis until it is around -8000.00 away from the start position.

In the rotateAndMove Script Properties, change the movementEnd to be 16000. This means that the Flying Car Entity will pass Checkpoint3 exactly in the middle.

Check the “simulate” checkbox and make sure that it is heading in the right direction, and that it still passes Checkpoint3 within jumping distance.

At the moment the car is travelling far too fast for the Player to successfully jump on board as it passes – there would be too much luck rather than skill which can be very frustrating. 

To tip the odds in the players favour, slow the speed of the car down by changing the rotateAndMove Script time Property to 20s.

Uncheck simulate when you are happy with the values of rotateAndMove.

Test this section of the game thoroughly before continuing. Try to board the car as it passes. You may need to tweak the time of the rotateAndMove Script to make sure that the jump is possible, and you might also choose to move the car closer or further away from the Checkpoint3 depending on what you deem to be a reasonable jump gap (I moved it around 50.00 further away from the Checkpoint edge).

To continue the jump puzzle, your Player needs somewhere to jump off before the Flying Car Entity respawns back at its origin. To keep this puzzle still within the realm of possibility you should add a stationary platform to jump onto. A crane will do nicely.

Open the Entity Editor for the Flying Car Entity once more. Make a note of its current position and move it in front of Checkpoint3 – refer back to the note you made of its original position to save time.

Open the Library and add the Crane Cabin Prop to your Hotbar. Also add the Crane Frame, the Crane Cable and the Crane Hook Props.

Add a Crane Cabin Entity to the game, and position it within jumping distance of the Flying Car Entity.

If you are unsure you can test the jump with Non-Drone Mode (Humanoid Mode) without having to Preview the game and run the gauntlet.

Now you know that the jump is doable, return the Flying Car Entity to its starting position. Move the Crane Cabin Entity in the opposite direction from the Flying Car Entity. Make sure you don’t go past the cars movementEnd position.

Once your Crane Cabin Entity is in the correct position, continue to build a reasonably equipped crane using the other Crane Props.

Test that you can make the jump from Checkpoint3, to Flying Car Entity, to Crane and exit the Preview.

The player will then jump from this crane to another crane. Repeat the steps to build another crane next to this one, facing the other direction.

Once you have built it, rotate it so that it points away from the greenhouse.

To be able to run all the way along this you may need to turn off collisions on the top middle section. To do this, open the Entity Editor for the top middle section.

Uncheck collisionEnabled.

This first jump is tricky enough to warrant adding Checkpoint4 to this second crane. Locate Checkpoint4 and move it to the middle of the crane so that the Player can save their progress, and respawn here if they fail the next jump.

Now to create the other Flying Car Entity

Add a Flying Car Entity the end of the crane so that you know that the jump is possible. Make sure the car is facing in the opposite direction.

Flying Car 2 needs to start from Flying Car 1’s final X-Axis position. Time for some maths! 

Take the original X-Axis position of the first Flying Car Entity (which you noted down earlier) and add the movementEnd value (16000), like so:

  • Flying Car 1 X-Axis position: -5850
  • Flying Car 1 movementEnd value: 16000
  • -5850 + 16000 = 10150 
  • Flying Car 1 final X-Axis position after movement: 10150
  • Flying Car 2 starting X-Axis position is therefore 10150

Move Flying Car 2 so that the starting X-Axis position is 10150.

Change Flying Car 2 movementEnd to -16000. This will make sure it moves in the opposite direction.

Test your timed-jump puzzle all the way through thoroughly.

Obstacle 5: Parkour Jump Puzzle

The final section of the level will take part on a separate Voxel Mesh skyscraper which you will need to build.

Open the Library and navigate to the Voxel Meshes tab.

Select “Create New Asset” and name it Skyscraper.

Press OK and add it to your Hotbar. Close the Library.

Add the Skyscraper Voxel Mesh to the world. The Voxel Mesh should be close enough that you can jump on it from the Flying Car.

Open the Entity Editor for this Voxel Mesh and move the Voxel Mesh using the X-Axis position only so that it is near Flying Car 2’s end position.

Close the Entity Editor for the Skyscraper Voxel Mesh and move the Drone so that the Skyscraper Voxel Mesh is visible in your view. 

Open the Library and add the Skyscraper Voxel to your Hotbar.

Switch to the Voxel tool and build a platform to jump to using the Skyscraper Voxel.

Now continue to build a skyscraper around this platform. Try to copy the same design as this one in order to be able to follow along on the next section.

A final part of this section will be a parkour jump puzzle around the side of the skyscraper. This section is supposed to be very hard, but still not impossible.

Use a Billboard Prop to create a walkway from the platform to the side of the skyscraper.

Use the Entity Editor to fine-tune it’s position. It must be possible for the Player to run along the top of it from the platform to the side of the skyscraper. 

Make sure to position it past the right hand corner so that the Player can run around the side of the skyscraper.

Use Metal (Steel) Voxels to create a walkway along the top of the Billboard.

Use Air Vent Curve and Air Vent Straight Props to create “vent” style steps up the side of the skyscraper. You may need to test this repeatedly to make sure its difficult by manageable.

Finally move Checkpoint5 to the top of this skyscraper.

From here your player will be able to look back on their entire journey with satisfaction. Test your level through several times to make sure it is possible (and hopefully fun) making adjustments as you see fit.

Success! You have now completed building the basic structure of this monumental obstacle course. 

Next Steps: Polish And Tidy

The next step part of building a level is tidying up the level, improving optimisations and “dressing” the level to really give players a wow moment, and start to layer on your own unique flair. 

Categories
Basic Tutorials

Basic Coding 5: Physics

Preface

Once you understand the basic building blocks of coding, you can start to experiment with some of the resources that are available only to programmers. Game engines, like Crayta, have a way that programmers can interact with core functionality, which is called an API (Application Programmer Interface). 

Introduction

The Unit 2 Games developers have been hard at work to make sure that Crayta has some useful features you can interact with through code. One of these features is the physics engine.

The physics engine is an immensely powerful tool in Crayta. The physics engine controls the game physics including gravity and friction. It also means that you can apply forces to Entities within the game, and they behave in a simulated physical space. In this tutorial, you will find out about a couple of different ways that you can apply forces to Entities within Crayta. Let’s get going.

Create A Game

Create a new blank game and enter the advanced Editor.

Start a new blank game.

Add A Trigger 

A Trigger is an invisible Entity which knows if another Entity is within it, or has entered or exited it. Adding a Script to a Trigger allows us to access these functions, and to perform actions when they occur.

In the Primitives section of the Library you will find a Trigger

You can find the Trigger Primitive in the Primitives section of the Library.

Add a Trigger to your game. It will need some configuration before it can be useful.

Add a Trigger to your game.

Click on the Trigger and change the size of the box to 200.0, 200.0, 200.0. You can find the size Property in the Entity Editor for the Trigger Primitive.

Change the size to 200.0 200.0 200.0

This will make the box consist of a larger volume. You may need to reposition the Trigger once you have resized it.

Reposition your Trigger so that none of it is below the level of the ground.

Add a new Script to the Trigger. Call the Script “LaunchMe” and enter the Script editor by clicking on the pencil. You will need to know where the Trigger is when it comes to testing the game (as they are invisible during gameplay).

Add a new Script to the Trigger called LaunchMe. To help me find it, I’ve added some lovely tile Voxels under the Trigger.

Add A Trigger Function

The purpose of this LaunchMe Script is to launch the player into the air when they enter the Trigger.

There are two “hook” functions that specifically relate to a Trigger in Crayta. These are:

  1. OnTriggerEnter – which is called when an Entity intersects or enters the Trigger 
  2. OnTriggerExit – which is called when an Entity that did intersect the Trigger no longer does so

Both of these functions can take a parameter in the brackets which refers to the Entity that entered or exited the Trigger.

Within your Script, add the OnTriggerEnter function and include a Print statement, so that you can test that this is working. You can try to write this yourself, or you can copy the following:

function LaunchMe:OnTriggerEnter(other)
    Print("Something entered the Trigger")
end

Test your Script by playing your game. When you enter the Trigger volume you should be able to see the statement appear in the Console.

Launch The Character

In a previous tutorial you looked at using conditional (if) statements in order to check the value of a variable. You can use this same technique in the OnTriggerEnter function to check what type of Entity just entered the Trigger.

Tech Tips: Type-Checking

Sometimes it is not possible for you to be sure of exactly what type of data is contained in a variable. For example, a variable that is created whilst the game is running could contain a Character, or an Entity

Conditional statements can come to the rescue here, and ensure that the right type of data is being treated the correct way. You can write:

if aVariable:IsA(datatype) then

Which will ensure that the variable is the correct type of data before trying to run functions on it.

The Launch() function is a specific function that only exists on one type of Entity called a Character. You will need to check that the Entity that entered the Trigger is a Character before you can run the Launch() function. Add the following code to your OnTriggerEnter function:

function LaunchMe:OnTriggerEnter(other)
    if other:IsA(Character) then
        other:Launch( Vector.New( 0, 0, 2000 ) )
    end
end

This code is called automatically by Crayta when something enters the Trigger. The Script checks the type of Entity. If it is a Character, then the Script will call the Character’s Launch() function. 

Tech Tips: Vector.New(x, y, z)

Notice that we have also included a Vector.New… parameter in the Launch function. This value tells the Launch function which direction, and how powerfully, we need to launch the character. The Vector is the type of data, so here we are giving the three values, which relate to the positional axes in the 3D game. For example:

Vector.New( x, y, z)

Where:

X = left (-) / right (+)
Y = towards (-) / away (+)
Z = down (-) / up (+)

The launch code will fire the Character upwards with a force of 2000.

Save the Script. Return to the game and test your Trigger by running your character into it. You should find that it launches you into the air.

Walking into the Trigger should launch you into the air. Mmm, physicsy.

Adding A Thruster

Within Crayta’s physics engine is the ability to add a Thruster to an Entity. A Thruster does exactly what it sounds like, it applies a continuous thrust force to an Entity.

You can add a Thruster to any Entity to make it fly! 

In the game Editor, add a new Prop entity – pick the Bath Tub from the Library and place it somewhere in your scene.

Add a new Prop that you want to fly through the air. I am using a bathtub.

Tech Tip: Size = Weight

In Crayta physics, the larger an Entity, the heavier it is. This is the default setting because as a rule of thumb, it is similar to the real world. For example, a bathtub is much heavier than a banana.

When you make something fly, you have to lift it off the ground using a force strong enough to take the Entity’s weight. The amount of force you give the bathtub will be much greater than what you would need to achieve the same effect with a banana, and much less than what you would need to make a bank vault fly.

You can change the density (and therefore the weight) of an Entity in the Entity Editor. This way, you could make a banana as dense as a house, and very hard to lift off the ground.

Select the Bath Tub Entity and make sure that the physicsEnabled checkbox is ticked.

Make sure that physicsEnabled is checked on the flying bathtub.

Add a new Script. Call the Script FlyMe. Enter the Script Editor.

Creating a Thruster is simple enough. Within the Init() function that is already prepared, add the following code:

self.thruster = self:GetEntity():CreateThruster()
self.thruster:SetForce( Vector.New( 0, 0, 150000 ) )

Notice that we are using Vector.New… again to set the force of the thrust here. We have to use a much higher value, because a Bath Tub is very heavy – Crayta simulates the weight of the objects based on their size.

Save the Script and check the Simulate checkbox on the bathtub. You should find that the Bath Tub takes off and flies into the air. You can use the simulate checkbox to test some of your coding without needing to playtest the game (although it’s still a good idea to playtest as often as possible).

Goodybe bathtub!

Uncheck the simulate checkbox to return the bathtub to it’s original position.

Triggering The Thruster

Now that you have made something fly, it’s time to learn how to control it somewhat. You are going to use another Trigger to do this. When a Character Entity enters the Trigger, it will turn on the Thruster on the Bath Tub. When a Character Entity exits the Trigger, it should turn off the Thruster.

To help your FlyMe code to know whether the Thruster should be on or off, you will need to add a boolean variable to the FlyMe Script. Open your FlyMe Script, and change your Init function to be like the following:

function FlyMe:Init()
    self.thruster = self:GetEntity():CreateThruster()
    self.thrustOn = false
end

You are no longer setting the force of the Thruster, and you have created a variable, thrustOn, and set it to false by default. This means that if we were to run the game the Bath Tub would no longer take off, because the Thruster has a thrust of 0.0 in all directions by default.

Create the following function in the FlyMe Script:

function FlyMe:ToggleThruster()
    if self.thrustOn then
        -- turn the thrust off
        self.thruster:SetForce( Vector.New( 0, 0, 0 ) )
        self.thrustOn = false
    else
        -- turn the thrust on
        self.thruster:SetForce( Vector.New( 0, 0, 150000 ) )
        self.thrustOn = true
    end
end

If you read through the code, you can see that it is “toggling” the Thruster on and off, by setting the amount of force that the Thruster has. The code uses the thrustOn variable to determine whether the Thruster is on or off (remember it is set to off in the Init function at the start). If the Thruster is on, then turn it off, and if it is off then turn it on. 

Tech Tips: Flags

thrustOn is a specific type of variable that programmers call “flags”. A flag is essentially a boolean value, which describes the state of something that can only have two states. Here it is the Thruster, and we are using a flag to tell whether the Thruster is on or off.

Now that we have made a function which can turn the Thruster on or off, we can call this from some of the inbuilt Events within Crayta. Return to the game Editor.

Create a new Trigger. Make sure to set the size, and reposition as required.

Add the Trigger to your Game World. Set the size and position accordingly. You can place another Prop or Voxels underneath it for testing purposes. This time I have selected a some beautiful Party Voxels.

Select the new Trigger that you just added (trigger2 in my case).

Use the Event boxes to add Event Listeners to the onTriggerEnter and onTriggerExit boxes. Make them both equal the following:

Entity: Bath Tub (or the Prop Entity you selected)
Script: FlyMe
Event: ToggleThruster

Add the bathtubs FlyMe:ToggleThruster function to the onTriggerEnter and onTriggerExit Events for the second Trigger.

Using the inbuilt Trigger Enter/Exit Events Listeners means you can very quickly link these Events to a function that you want to call. You can add more than one function to each Event, and they don’t have to be on the same Entity. Using the Packages and the tools that are available to you (like the physics engine) is all part of being an efficient programmer.

Test your game. When you enter the new Trigger, you should find that the Bath Tub levitates into the air. When you exit the Trigger, you should see it fall back to land.

Impress your friends by levitating a bath!

Recap

Success! You have now embarked into the world of physics within Crayta. Now that you have a basic understanding of Thrusters and launching the main character you can make lots of flying inventions to pilot or use as obstacles.

Adding Polish

Try creating a flying Bath Tub that you can easily operate:

  • Use trial and error to alter the amount of force that is suitable to make the Bath Tub more gradually fly into the air when you enter the Trigger
  • Use trial and error to select an amount of force that can make the Bath Tub hover when you leave the Trigger
  • Add another Trigger. Alter the FlyMe Script so that it is possible to have 3 different states for the Bath Tub: Rising, Hovering and Falling. Try using a number variable instead of the flag – when the number is 0 the Bath Tub is rising, when the number is 1 the Bath Tub is floating etc.
  • How could you add thrusters that move the Bath Tub in different directions?

Next steps

Congratulations. In the next tutorial in this series we put together everything you’ve learned so far to make a Highly Dangerous Football Game!

Categories
Basic Tutorials

Basic Coding 4: Conditionals

Preface

Variables are useful for storing data, which means we can use them for lots of things. One thing that makes them even more interesting is examining the data that is stored, and changing the behaviour of a game based on that data. Introducing…conditionals!

Introduction

A “conditional” is a term used by programmers to refer to a line of code which asks a “yes or no” question, and then runs different code depending on the result. If the result is true, the game might continue in one direction. If the result is false, the game might do something else. Using our flowchart analogy from the previous Code Tutorials, a conditional looks like this:

Developers use conditionals all the time, and they play a crucial role in games that you can win or lose. In this tutorial, you will learn how to write a conditional statement and how to use it in a game.

Create A Game

Create a new blank game and enter the Advanced Editor.

Start with a new blank game.

Add A Prop

Add a Prop to the Game World. Choose a Prop that might explode (we will use a Barrel).

Add a Barrel (Exploding) Prop

Create A New Script

With the Barrel Entity selected, use the Entity Explorer on the right hand side to add a new Script. Entity -> Add -> Script -> New Script. Call your Script TimedExplosive.

Add a Script called TimedExplosive to the barrel.

Open the Script by clicking on the pencil icon in the Entity Editor. 

Click the pencil icon to edit the Script.

Functional Breakdown

The flowchart for a timed explosive device might look something like this:

As you can see, there are a few steps that we need to code. The core of this code will occur on the OnTick function, which gets called every frame.

Creating A Timer

Within the Init() function, create a variable to store the time remaining as a number. Call this variable timeRemaining and set it to 5, which will mean 5 seconds:

function TimedExplosive:Init()
    self.timeRemaining = 5
end

In order to keep the time, you will need to write some code within the OnTick function, which is called every frame. However, like most games, Crayta’s “frames per second” is variable, so we won’t necessarily have the exact same time interval between function calls.

Tech Tips: Frames And Frame Rate

A frame, in this context, is referring to a moment in time when Crayta is drawing the visible aspects of the game on your screen. The speed that Crayta aims to do this is 60 times every second, which is referred to as the Frame Rate. A Frame Rate is measured in “frames per second” or FPS, and whilst Crayta aims to stick to 60 FPS, it is not always possible to rely on this.

The frame rate of a game can vary during gameplay, depending on a variety of factors. These factors include: how complicated the visual components are, how fast your computer is, and whether your computer is trying to run other programs at the same time as Crayta (amongst others).

In order for our timer to be accurate, it cannot rely on the OnTick() method to be called at exactly the same interval. Fortunately, Crayta’s OnTick function gets given a variable that can tell us how much time has passed since the last time OnTick() was called. We can use this variable to reduce the timeRemaining variable.

Add an OnTick function to your Script.

function TimedExplosive:OnTick(deltaTime)

end

By putting deltaTime in the brackets of this function, we can store the value that is passed to this function, which is the amount of time since the last time this function was run. Now you just need to reduce timeRemaining by that value. Add the following code to your OnTick function.

function TimedExplosive:OnTick(deltaTime)
    self.timeRemaining = self.timeRemaining - deltaTime
    Print("Time remaining: ", self.timeRemaining)
end

Tech Tips: deltaTime?

It doesn’t particularly matter what identifier you give a variable (as long as it doesn’t start with a number), but there are some common terms that are used by programmers so that code can be easily read and understood now and in the future. 

Delta is a Greek letter (Δ) that is used in Maths to denote the difference between two values. Here, Delta is used because it stores the difference between the last time this function occurred, and the present time in seconds.

Notice that this code also outputs the time remaining to the Console, so that you can test that this code is working.

Run the game.

Press ‘O’ to Open the Console and ensure that the timeRemaining is decreasing at a steady rate. (Hint: You can press ALT to turn your Console fully opaque).

Check that the time is decreasing at a steady pace (it should be one whole number per second).

Adding A Conditional Statement

At the moment, the timeRemaining continually counts down, into the negative numbers and onwards to negative infinity. If you want the timer to do something when it reaches 0, you will need to use a conditional.

Add the following line of code to your OnTick function:

function TimedExplosive:OnTick(deltaTime)
    self.timeRemaining = self.timeRemaining - deltaTime
    Print("Time remaining", self.timeRemaining)
    if (self.timeRemaining <= 0.0) then
        Print("Time is up!")
    end
end

This code stipulates that if the timeRemaining reaches 0, output that the timer has finished to the console. 

If we want to stop the timer counting down when it reaches 0, to stop it entering the negative numbers, we will need to use an “else”.

Tech Tips: If, Else, Else if

A conditional can check “if” something is true before performing some code, but it can also run different code if the condition is not true using the keyword “else”. This makes sense if you read the code like it’s English:

if conditionA is true then
Do something
else
Do something different

You can add further conditions to the else aspect in order to branch in many different directions. For example:

if conditionA is true then
Do something
else if conditionB is true then
Do something different
else
Neither condition is true, do something different from either

You can chain up as many if…else if…else if… as you like, but bear in mind that the conditions will be checked in the order you write them. So if conditionA was true, then it doesn’t matter if conditionB is true as well, Crayta will only run the code that was specified for conditionA (do something).

Change your timer Script so that it uses an else before it decreases the timeRemaining:

function TimedExplosive:OnTick(deltaTime)
    if (self.timeRemaining <= 0.0) then
        Print("Times up!")
    else
        self.timeRemaining = self.timeRemaining - deltaTime
        Print("Time remaining", self.timeRemaining)
    end
end

Save your Script, and return to the game Editor to test your game.

You should see the message “Time’s up” appear when the countdown has reached 0, instead of negative numbers.

Adding Explosions

Now that you have used a conditional, you can celebrate by making the barrel explode when the timer runs out.

In the game Editor, add an explosion Effect and an explosion Sound to your prop.

Add an explosion Sound and Effect to your barrel (it is about to explode after all).

Return to your Script.

To play a Sound or an Effect, you will need to set it’s active variable to true. In order to set the active variable to true, you will need a way to reference these Entities.

Add two Properties to your Property Bag. Remember, adding Property will show the variable in the Crayta game Editor, so you can change the value there:

TimedExplosive.Properties = {
    { name = "ExplosionEffect", type = "entity" },
    { name = "ExplosionSound", type = "entity" },
}

Go to the game Editor. Click on the Prop Entity set to explode.

Set the ExplosionEffect and ExplosionSound Properties to hold the Explosion Effect and Sound Entities

Hookup your Sound and Effect to the respective Properties on the TimedExplosive Script in the Entity Editor.

Whilst you are in the game Editor, make sure that the Explosion Effect and the Explosion Sound both have their Active checkboxes unticked.

Make sure that the explosion Sound and Effect have their active boxes unticked.

Return to your Script.

To set the active variable on the Sound and the Effect, add the following lines of code underneath your Print(“Times up!”) line:

        self.properties.ExplosionEffect.active = true
        self.properties.ExplosionSound.active = true

Reading through the code, you can see that the active variable is being set to true.

Before continuing, it is also a good idea to remove the barrel once it has exploded (things usually disappear when they explode…). To do this, you need to make your barrel invisible, and turn off collisions. Your final conditional statement in your OnTick function should look like this:

function TimedExplosive:OnTick(deltaTime)
    if (self.timeRemaining <= 0.0) then
        Print("Times up!")
        self.properties.ExplosionEffect.active = true
        self.properties.ExplosionSound.active = true
	self:GetEntity().visible = false
	self:GetEntity().collisionEnabled = false
    else
        self.timeRemaining = self.timeRemaining - deltaTime
        Print("Time remaining", self.timeRemaining)
    end
end

That’s it! Now test your game and wait for the timer to run out. 

Your final code should look like this:

local TimedExplosive = {}

-- Script properties are defined here
TimedExplosive.Properties = {
	{name = "ExplosionEffect", type = "entity"},
	{name = "ExplosionSound", type = "entity"},
	--{name = "health", type = "number", tooltip = "Current health", default = 100},
}

--This function is called on the server when this entity is created
function TimedExplosive:Init()
	self.timeRemaining = 5
end

function TimedExplosive:OnTick(deltaTime)
	
	if (self.timeRemaining <= 0.0) then
		Print("Times up!")
		self.properties.ExplosionEffect.active = true
		self.properties.ExplosionSound.active = true
		self:GetEntity().visible = false
		self:GetEntity().collisionEnabled = false
	else 
		self.timeRemaining = self.timeRemaining - deltaTime
		Print("Time remaining: ",  self.timeRemaining)
	end
	
end

return TimedExplosive

Recap

In this tutorial, you learned about framerates, and how to use a variable to create a timer. You also added a conditional in order to do something when the timer runs out, and to do something else if the timer had not run out.

Adding Polish

You can use this same Script to add timers that do a variety of different things. Based on Scripts that you’ve learned in previous tutorials, experiment by doing the following:

  1. Add an Entity to the game which a player can interact with
  2. When the player interacts with it, it starts a timer that lasts 2 seconds 
  3. When the timer runs out a door opens

Next steps

Conditionals are very powerful, and really useful for making a dynamic and engaging game. The last topic in this series looks at how you can use these fundamental principles of programming with some of the inbuilt systems in Crayta. Next up, physics!

Categories
Basic Tutorials

Basic Coding 3: Functions

Preface

Functions are reusable blocks of code, and they exist in most programming languages. Programmers find functions useful for organising their code and saving time, as they don’t have to copy and paste the same lines of code over and over again. Instead, they can wrap the code in a function.

It is good practice to ensure that a function is given a useful name which describes what the it does, and to try to keep functions short-and-sweet. A function should ideally only perform one action, which makes it easier to debug and can often help to make the function more reusable.

Introduction

When a line of code tells Crayta to run a function, we say that we are “calling” that function. You have already written code that exists within a function (Init() OnInteract(), and code which calls other functions (Print()).

This tutorial aims to clarify some of the terminology around functions, and their use in Crayta. You will look at:

  • The use of functions
  • Functions return a value
  • Calling a function and using the returned value
  • Writing a function

Create A Game

Create a new empty map and enter the Advanced level editor.

Add A Door

Use the Library to select a Vault Door Prop, and add it to the game world.

Add a Vault Door Prop to the Game World.

Add A Door Script

Click on the VaultDoor Entity, and add a Script by clicking Entity -> Add -> Script -> New Script. Call the Script DoorScript.

Add a new Script to the door called DoorScript.

Open the Script Editor for the DoorScript.

The Problem

Within the DoorScript, we will be calling a function which plays an animation that is already attributed to the VaultDoor. Using the documentation, you can see that playing an animation on a Prop Entity is possible using the function:

Prop:PlayAnimation(string animationName)

As we did before, let’s break down our problem into a flowchart:

This time round, we want to play an animation on the Door Entity.

Animations are played by telling the Entity itself to play them, not just the Script we are working in. This means we need to get hold of the Entity before we can play any animations.

Get The Entity

Every Script which runs on an Entity has the ability to access the Entity itself, and it needs to do this to access information about it, or run functions in other Scripts

Tech Tips: Functions Return Values

You may already know that a function is a reusable block of code, but did you know that a function can also return a value? Just like a variable, a function can be thought of as a way of accessing data, and storing data for later. However, unlike variables, a function can contain runnable code, that can manipulate the data before it shares it.

For example, take a look at the following code:

function MyClass:MonthsInAYear()
    return 12
end

In this function, MonthsInAYear(), we are “returning” the number 12. This means if I call it, it will be replaced with that number. For example:

local months = MonthsInAYear() -- the number 12 is stored in the variable months

In this code, the variable months will store whatever is “returned” from calling the function MonthsInAYear().

Some functions return “void”, which means that the value they return is essentially nothing (think void as in space, where there is nothing).

Now that we know that functions can return a value, and that we can store this using a variable, we will put this into practice.

Create an OnInteract function in your DoorScript, which should look like this:

function DoorScript:OnInteract()

end

Within your DoorScript OnInteract() function, add the following line of code:

local entity = self:GetEntity()

This line of code runs the function GetEntity(), which is a function built-in to a Script in Crayta, and then stores the result of that in the variable “entity”. In our case the entity now holds our Vault Door.

We can now use the variable “entity” to access data about the Entity, or run functions on the Entity. For example (don’t actually do this), in order to get the position of the Entity, we could do:

Print(entity.position.x) -- this will print the position of the Entity to the console

Play The “Open Door” Animation

We know from the documentation that any Prop Entity has the function PlayAnimation, which takes a string as a value in the brackets:

Prop:PlayAnimation(string animationName)

The VaultDoor has two animations, “Open” and “Close”, so we can put either of these strings in the brackets of the PlayAnimation function to play those animations. If the animation has already played and the Prop is at the end of the animation in question, then nothing will happen.

To run the PlayAnimation function add the following code underneath the local entity variable declaration:

entity:PlayAnimation("Open")

The code in your DoorScript should look like this:

local DoorScript = {}
DoorScript.Properties = {}

function DoorScript:Init()
end

function DoorScript:OnInteract()
    local entity = self:GetEntity()
    entity:PlayAnimation("Open")
end

return DoorScript

Return to the Level Editor, and test your game. Try interacting with the Vault Door and you should see that it swings open.

You can now open the door by interacting with it during a game Preview.

Return to the Level Editor when you are happy that your code works.

Writing A Function

Opening the door when you interact with it is all well and good, but what if you want to open the door on other events? Or play a sound as well? This is when it might be useful to write a function to do this.

Tech Tips: Anatomy Of A Function

You have already written functions in Lua, and you know that they look like this:

function DoorScript:OnInteract()

end

Let’s break down the function declaration in a bit more depth

function – this is a keyword in Lua which states that we are defining a function

DoorScript – this is the name of the Script that this function belongs to

: – we use a colon to define that what follows is a “member” of this Script

OnInteract – this is the name of the function itself

() – the brackets can hold values that we can pass from the code calling the function to the function itself. If there is nothing in here, we still need to include the brackets, but we can leave them empty.

end – this is a Lua keyword that defines the end of this function

Write your own function in the DoorScript Script like so:

function DoorScript:OpenDoor()
    local entity = self:GetEntity()
    entity:PlayAnimation("Open")
end

Remove the code from within the OnInteract function, and replace it with the following to call the function:

self:OpenDoor()

Your DoorScript should now look like this:

local DoorScript = {}
DoorScript.Properties = {}

function DoorScript:Init()
end

-- function to open the door
function DoorScript:OpenDoor()
    local entity = self:GetEntity()
    entity:PlayAnimation("Open")
end

function DoorScript:OnInteract()
    self:OpenDoor()
end

return DoorScript

Test your game. The behaviour will be the same, but now we are calling the PlayAnimation function from our own function.

Opening The Door From Elsewhere

What if we wanted to open the door when we pressed a button, or pulled a secret lever? This is when functions are really powerful. We can call the OpenDoor() function from somewhere else.

Use the Library to add another Prop Entity to the game world. I have added a wall using some Voxels and placed a Key-Card Reader Entity on the wall next to the Vault Door Entity.

Add a Key-Card Reader near the Door Entity.

Open the Entity Editor for the Key-Card Reader.

Click on the “+” next to OnInteract, and use the menu system to select:

  • Entity: bankVaultDoor
  • Script: DoorScript
  • Event: OpenDoor()
Click on the + next to OnInteract in the Entity Editor for the Properties. Navigate to the onInteract Property. Then add the bankVaultDoor Entity.

Select your OpenDoor() function for the Event dropdown option.

Test Your Game

Preview your game. Try interacting with the Key-Card Reader (or the Prop Entity you chose) and ensure that the door opens. Success!

When you Interact with the Key-Card Reader, you should find that the door swings open.

Recap

In this tutorial, you have looked at how to call functions, how to write functions, and why functions are useful additions to the coders toolbox. You also saw how you can use a mixture of Crayta Entities, Community Scripts and your own code to make completely custom functionality.

Adding Polish

There are several more functions that may be of interest to you, depending on what you want your game to do. Just like the way you used the OnInteract() function, you might also want to try:

  • OnCollision() – called when something collides with this object
  • OnDamage() – called when something damages this object
  • OnTriggerEnter() / OnTriggerExit() – these are called on Scripts attached to a Trigger Volume Entity, when a player enters or exits the Trigger Volume
  • OnTick() – called every frame

To take this game further, and cement your understanding of functions, try the following:

  • Remove the code from the OnInteract() function on the DoorScript, so that the only way to open the door is by interacting with the Key-Card Reader
  • Using a variable on the DoorScript, make the game more challenging by needing to interact with the Key-Card Reader multiple times, before the door opens

Next steps

Functions and variables are the cornerstones of scripting, and a lot can be achieved with just those two. However, there is more that you can achieve once you start using conditionals, which make use of the data stored in variables in order to change the activity in the game and to create timers. Time to move onto Code Tutorial 4: Conditionals.

Categories
Basic Tutorials

Basic Coding 2: Variables and Datatypes

Preface

Now that you have played with Crayta’s Advanced editor, and had a go at coding, you can start to learn how to write your own code.

A lot of the principles of coding are the same regardless of the programming language. Many of the practices you learn in these tutorials will be transferable to other game engines, and to other software development also, so it’s worth investing a bit of time to ensure that you know what the code is doing. Make sure to “add polish” at the end, and play around with what you have learned to cement your understanding.

Introduction

Fundamentally, code is instructions that tells the computer how to manipulate data. By manipulating data in certain ways, we can play games, make barrels explode and fire bazookas.  

This tutorial looks at: 

  • Storing data in variables
  • Types of data we can store

Create A Game

Create a new blank game and enter the advanced editor.

Add A Mesh

Using the library on the left, add a Mesh to the game. I have added the Checkpoint. 

Add a Mesh to your game.

Create A New Script

With the Entity selected in the Entities Explorer on the right hand side, click Entity -> Add -> Script -> New Script. Call your Script InteractionCounter and press OK.

Create a new Script called InteractionCounter, attached to the Checkpoint.

We are going to count the number of times the player interacts with this object, and output the result in the console.

Creative Control: Interaction

Players can “interact” with Entities during gameplay by looking at an object and pressing X. The term interact can mean potentially any action, so it’s up to you as a game designer to decide what that interaction is. For example, interacting with a book Mesh could mean reading it and displaying some text, or picking it up and adding it to the players inventory, or throwing it at another player. If you can code it, then it can happen.

In this tutorial, you will be using code to count the number of times the player interacts with a single Entity.

Open the Script by clicking on the pencil icon in the Entity Editor

Open the Script for editing by clicking the Edit Script button.

To code a solution to this problem, we need to break the problem down into steps. Then we can code each step, one-by-one, and eventually reach our solution. Sometimes it can be useful to draw a flowchart to do this, so a flowchart for this problem would look like this:

Set Counter To 0

In order to “count” the number of interactions, we will need to use a variable. Variables are a way of storing data, so that we can refer back to it later, or change it. Here are the simplest types of data that variables can store:

Type of dataExample value
Number12, 15.6, 8, 0, -42
String“Hello World”, “My word”
BooleanTrue or False

Let’s look at an example. A variable myVariable, which is a Number might have the value 12:

local myVariable = 12

This means that I can use myVariable in my code like this:

self.position.x = myVariable  — This will move the Entity so that it’s x-coordinate is equal to myVariable, which is 12.

The benefit of using variables is that if we want to change what is stored inside them whilst the game is running. So for example, we can do:

self.myVariable = 12

self.myVariable = 15

self.position.x = self.myVariable -- This will move the Entity to x-coordinate 15

Tech Tips: Naming Variables

A variable can be called almost anything. It can include numbers, but it cannot start with a number. E.g.

local spooky4u = "Yes" -- allowed
local 2spooky4u = "Yes" -- not allowed

A variable name cannot include any spaces, so if you want to use multiple words, a general convention is to use “Camel Case”. Camel Case means every new word starts with a capital letter, but no spaces. For example, rather than

This is my variable name = 12 -- wrong

We would use:

thisIsMyVariableName = 12 -- correct

Be aware that the letter CASE is important in code. A variable all in uppercase MYVARIABLE will not be the same variable as one in camelCase such as myVariable, or in lowercase such as myvariable.

You can see that there is already some code in the InteractionCounter Script. When the game starts, the script’s Init() function is called.

--This function is called on the server when this entity is created
function InteractionCounter:Init()
    -- Any code placed in here will run when this function is called
end

We should use this as our starting point to accomplish the first step of our flowchart.

Replace the Init() function with the following code:

–This function is called on the server when this Entity is created

function InteractionCounter:Init()
	self.counter = 0
end

This means that when the game is started, a variable called “counter” is created, and made to hold the value 0.

Tech Tips: Variable Scope

Accessing a variable you have created may or may not be possible depending on the variable scope.

You can declare a variable in three different ways in Crayta. The way that you have declared it:

self.counter = 0

Means that we can use this variable only in this Script, but we can use it anywhere within this Script .

If we write the variable declaration like this:

local counter = 0

This would mean we could only use the variable in the function, conditional or loop that it is within. It wouldn’t be accessible anywhere else.

If we write the variable declaration in the Properties Bag at the top like this:

InteractionCounter.Properties = {
    {name = "counter", type = "number", default = 0},
}

Then we can access this property anywhere, including the Crayta Level Editor in the Entity Editor, as well as other Scripts.

When User Interacts…

A Crayta Script has different functions that are called when an Event occurs in the game. One of these functions is OnInteract(), which is called when a Player interacts with an Entity.

The Init() function was automatically added to the Script when you created it, but the OnInteract() function was not. You will need to add this yourself. Add the OnInteract function to your code, so that your Script now looks like this:

local InteractionCounter = {}

-- Script properties are defined here
InteractionCounter.Properties = {
	-- Example property
	--{name = "health", type = "number", tooltip = "Current health", default = 100},
	{ name = "thing", type = "string" }
}

--This function is called on the server when this entity is created
function InteractionCounter:Init()
	self.counter = 0
end

function InteractionCounter:OnInteract()

end

return InteractionCounter

Increase Counter By 1

As described earlier, one of the benefits of using a variable to store data is that we can change it whilst the game is running. In our situation, we will need to change the value of the variable that we use to count the number of interactions – we will need to increase the value by 1 each time a Player interacts with the Entity.

We already know that the OnInteract() function is called when a Player interacts with this Entity, so we know that we need to increase the counter within this function.

We don’t necessarily know what value the variable will be when we want to update it, so we will need to change the value relative to whatever it holds at the time.

We can’t do this:

function InteractionCounter:OnInteract()
    self.counter = 1
end

Because the next time this function is called, it will just set the counter to 1 again. This will perform the following:

EventDescription
Game startedself.counter set to 0
Player interacts with Entityself.counter set to 1
Player interacts with Entityself.counter set to 1
Player interacts with Entityself.counter set to 1

Therefore, we need to use it’s own value in the arithmetic. So update your OnInteract() function:

function InteractionCounter:OnInteract()
    self.counter = self.counter + 1
end

Now our script does this:

EventDescription
Game startedself.counter set to 0
Player interacts with Entityself.counter set to self.counter + 1 = 0 + 1 = 1
Player interacts with Entityself.counter set to self.counter + 1 = 1 + 1 = 2
Player interacts with Entityself.counter set to self.counter + 1 = 2 + 1 = 3

Output The Counter To The Console

As a developer, it’s really useful to be able to communicate from the code to the Player testing the code without needing to build the User Interface to do this. Handily, Crayta includes a Console, which is a simple way to send messages from the code to the Player.

To send a message from the code to the player, we can use the Print() function. We will need to call this function to output the value of self.counter. 

Change your OnInteract() function to the following:

function InteractionCounter:OnInteract()
    self.counter = self.counter + 1
    Print("You have interacted " .. self.counter .. " times")
end

Notice that we put what we want to output between the brackets of the Print() function. Also, remember to pay attention to the CASE of the letters.

Tech Tip: Concatenating Strings

Just in case you missed it, a “string” is the term programmers use when talking about words and alphanumeric characters stored in a variable) together.

In most programming languages, you can join multiple strings together, and turn them into one long string. This is called concatenating.

In Lua, to join two strings together you can use the notation .. in between two strings you want to join together. Here, you put this between the count variable and a string. It temporarily transforms the count variable from “number” datatype, into a “string” datatype, so that it can be output to the Console.

Your final code should look like this:

local InteractionCounter = {}

-- Script properties are defined here
InteractionCounter.Properties = {
}

--This function is called on the server when this entity is created
function InteractionCounter:Init()
  self.counter = 0
end

function InteractionCounter:OnInteract()
  self.counter = self.counter + 1
  Print("You have interacted " .. self.counter .. " times")
end

return InteractionCounter

Testing

Save the script (File -> Save) and return the Game tab.

Preview the game. To open the Console press “o” on your keyboard.

Interact with the Entity, and you should see that the Console outputs the value of your counter.

Interact with the Mesh to see the Console print your counter variable.

Recap

In this tutorial we explored the concept of variables. Whilst the game we made is very primitive, it shows how it’s possible to store data within Crayta, and recall that data when necessary. Variables are immensely powerful, and a fundamental building block of coding.

Adding Polish

Try adding the following to cement your understanding of variables:

  • Create a variable called outputString in the Property Bag at the top. Make it of type string. Set the variable to hold “Counter is “ in the Level Editor.
  • Use outputString in the Print() statement that we wrote, so that it outputs the outputString followed by the counter, e.g. Print(self.properties.outputString .. self.counter)

Next steps

The next coding tutorial looks at functions in a bit more depth, and how we can use functions to make a timer.

Categories
Basic Tutorials

Basic Coding 1: Exploding Barrels

NOTE: A keyboard and mouse is needed for these coding tutorials, so that you can access Advanced creation mode (by pressing the TAB key).

Coding enables you to add dynamic interactions to your game, and gives you more creative freedom to experiment and make something that really stands out.

This series of tutorials is all about getting to grips with coding in Crayta. If this is your first time with Crayta, you might want to visit the Basic Tutorials, which go over the basic user interface of Crayta and some of the terms we will be using in this tutorial. Otherwise, if you are ready to jump in, let’s get to it!

Preface

Your first experience with coding could be a daunting experience. That’s why this tutorial is aimed at people who have never tried coding before, or have very limited experience. This tutorial will cover:

  1. Adding scripts to game objects
  2. Triggering some code with player interaction
  3. Using code to manipulate the game world
  4. Creating reusable templates

To follow this tutorial, you will need access to a version of Crayta with keyboard and mouse peripherals.

Creating The Game

To start, create a new blank game, or revisit one you already have in Create mode. Call your game Exploding Barrels.

When you have the game open in Create mode press TAB to enter Advanced Editor mode. 

Advanced Editor mode.

Adding Entities

In your library, click on the Library dropdown and select Meshes

Meshes are 3D objects you can place in your scene. Select Barrel (Exploding) and place it in your world with a left click. You are going to make this Entity explode when the player’s character touches it.

Select Barrel (Exploding) from the Meshes menu.
And place one in your Game World.

Creative Control

Whilst this tutorial uses a barrel, you don’t have to. Get creative! Maybe your character is trying to avoid homework, or dodge exploding axes. What’s the story here? Think about your game theme and use something that adds an original and exciting edge to your game.

Placing an Entity in the Game World will bring up the Entity Editor window, displaying the Entity’s Properties.

In the Entity Editor window on the right you can see the properties of the barrel. You can change these values by clicking on them and entering new values, or in small increments by using the arrow keys. 

Tech Tip: Entities In Depth

When you place a Mesh in your game Crayta behaves like a factory, duplicating the Mesh and giving it attributes which are required for it to exist in your game, such as it’s position and rotation. In order to distinguish between the Mesh in the Library, and the Mesh in the game, a Mesh which has been placed in a game is called an Entity

In the case of the ExplodingBarrel the Mesh is ExplodingBarrel, and the Entity is the specific instance of ExplodingBarrel in the game world.

If we were to place a new ExplodingBarrel in our game we would have another Entity. Each Entity will have the same attributes, but can have different values for those attributes, i.e. all ExplodingBarrel Entities have position and rotation attributes, but they can hold different values for each Entity.

Click the pencil next to the Name property and change the name of your Entity to ExplodingBarrel.

Great! 

Tech Tip: Organisation

It’s good practice to name your Entities in the Game World because it makes it much easier to navigate and maintain as the world becomes more complex. 

Do it from the start. It may seem trivial with only one or two Entities, but as your game level grows it becomes more time consuming to go back and organise it, or fix errors that have occured due to poor organisation.

You are going to make the barrel explode when the player walks into the barrel. Firstly, press F5 to play your level. Walk your character into the ExplodingBarrel. What happens? Nothing? That’s because we haven’t told Crayta how to respond to the player running into the object, or even that it needs to pay attention. And that’s what we are going to cover in this tutorial.

Press F5 again to return to the Advanced Editor.

Adding A Script

Make sure that your ExplodingBarrel entity is selected by clicking on ExplodingBarrel in the Entity Explorer. Add a new script from the Entity Editor toolbar by clicking Entity -> Add -> Script -> New Script.

Select Entity > Add > Script > New Script

Name your script ExplosionScript and press OK.

You’ll see that the ExplosionScript gets its own section in the Inspector window when ExplodingBarrel is selected. 

Click the edit script button next to the ExplosionScript’s scriptName to open the code editor.

Click the pencil icon next to the Script name to open it for editing.

You should see the following:

local ExplosionScript = {}

-- Script properties are defined here
ExplosionScript.Properties = { 
  -- Example property -- {name = "health", type = "number", tooltip = "Current health", default = 100},
}

--This function is called on the server when this entity is created
function ExplosionScript:Init()
end

return ExplosionScript

Tech Tip: Code?

The Script above contains code.

Code is a set of instructions that we give the computer. We have to write it in a way that both computers and humans can understand it, which is why it seems like an alien language some of the time. Learning to read and write code is like learning any new language, and (with a bit of practice) we can become fluent in reading and writing these instructions.

Different applications (including games) use different programming languages. The programming language we use in Crayta is called Lua which is a scripting language widely used in the games industry.

Tech Tip: Comments

Sometimes code can be difficult to understand, which is why most programming languages include a way of writing comments within the code. A comment is a segment of code which is ignored by the application.

Comments are written by developers (like you!) in order to describe the code from a human perspective. This way, if we forget (or don’t know) what the code itself is doing we can read the comments which will hopefully explain it to us.

In Lua, a comment is specified with with 2 hyphens(“–“) at the start of the line of code. For example:

-- This is a comment because the line starts with two dashes

Replace all the code in the script with the following:

local ExplosionScript = {}

-- Script properties are defined here
ExplosionScript.Properties = { 
-- Example property --{name = "health", type = "number", tooltip = "Current health", default = 100},
}

--This function is called on the server when this entity is created
function ExplosionScript:Init()

end

function ExplosionScript:OnCollision()   
  self:GetEntity().visible = false    
  self:GetEntity().collisionEnabled = false
end

return ExplosionScript

Can you spot what has been added?

...
function ExplosionScript:OnCollision()   
  self:GetEntity().visible = false    
  self:GetEntity().collisionEnabled = false
end
...

We have added one small chunk of code towards the end of the script. Notice the last line is still return ExplosionScript. This will always need to be at the bottom of the script.

Let’s read through what we’ve added…

function ExplosionScript:OnCollision()    
  self:GetEntity().visible = false    
  self:GetEntity().collisionEnabled = false
end

Line 13 states that Crayta should only run the code on line 14 when the player touches the ExplodingBarrel (OnCollision). When the player touches ExplodingBarrel, Crayta will run through each line of code until it reaches the end on line 16.

Line 14 uses self:GetEntity() to get the entity that this script is attached to, in this case, the ExplodingBarrel. It then sets ExplodingBarrel’s visible property to false. You can perform the same action by checking the visible checkbox in the Property window. 

On line 15, we use self:GetEntity() to get the entity again but this time we set the collisionEnabled property to false. This means the player will be able to walk through the (now invisible) ExplodingBarrel.

Save your script (CTRL + S) and return to the Game screen by clicking on the Game tab.

Preview your game and try walking into your ExplodingBarrel. You should see it magically disappear. You should also be able to move freely about where it once stood. If so, give yourself a pat on the back. If it doesn’t, take another look at your code and see if there is anything different from the one supplied above.

Adding Effects

With your game scene window open, use the Library dropdown to select Effects and choose Fire Explosion Large. Left click to place it in your scene on the ExplodingBarrel. Take a look at the Entity Explorer

Select Fire Explosion Large from the Effects menu in the Library.
Add it to the barrel in your game.

If your Fire Explosion Large entity is not a child of ExplodingBarrel then use the World Tree to click and drag Fire Explosion Large onto ExplodingBarrel.

Tech Tip: Parents and Children

Crayta uses a hierarchy system to group things together. Any entity can have another entity as a child (and children can have their own children too). This is a great way of grouping things together, and keeping things neat and ordered in Crayta. 

If you aren’t sure where your entity is in the scene hierarchy take a look at your World Tree. Child entities are listed immediately after their parent, and are indented the next level in, like a sub-list.

Be careful: Moving and rotating things only works from the top down. Moving a parent will move its children, but moving a child will reposition it relative to the parent, it won’t move the parent too!

Use the property inspector to rename your explosion Effect to “Explosion” and preview your game (F5). You should see Explosion explode as soon as the game starts. That’s good, but it’s not quite right. We don’t want things just randomly exploding at the start of the game, so now is the time to return to the editor and fix that (F5 again to return).

Select your explosion and use the Entity Editor to uncheck “active”.

If you preview your game again you should see that Explosion no longer explodes at the start. This tells you that setting your explosion’s “active” checkbox to true makes it explode. You can confirm this by clicking the checkbox on and off, and watching Explosion explode in the editor.

To make the Explosion explode during gameplay we will need to use a script to set the Explosion’s “active” property to true. Fortunately this is easy to add to the ExplosionScript. Select your ExplodingBarrel and click the Code Edit button to open your ExplosionScript.

Using code to reference something that exists in the game means we need to add a new property to the Property Bag.

Tech Tip: Properties

A property is like a shoebox we fill with data. By storing data in these “shoeboxes”, we can use and change them whilst the game is running. We always aim to use a descriptive name for our property, so that we can remember what it is later on.

The list of properties in a script is called a Property Bag. One script can have many properties in the property bag, each one a reference to a different piece of data. Properties can contain numbers, words, true or false values, or even other objects that already exist in our game. 

Use the following code to add a new property with the name “explosionEffect” to the Property Bag in ExplosionScript:

ExplosionScript.Properties = {    
  { name = “explosionEffect”, type = “entity” }
}

ExplosionScript.Properties = { declares that our ExplosionScript has a Property Bag. The properties are listed between the brackets starting with the open parenthesis { at the end of line 3, and finishing with the closed parenthesis } on Line 5. 

Within the parentheses {} Line 4 is declaring a single Property in our Property Bag, named “explosionEffect”. It also states that the explosionEffect Property is of the type “entity”. This means Crayta is expecting us to set this to one of the entities in our game world (such as a Mesh Entity, Sound Entity or other Entity). We will use this property to store a reference to our Explosion Effect.

We use the explosionEffect Property in our script further down. Let’s look at lines 10 – 14…

function ExplosionScript:OnCollision()    
  self:GetEntity().visible = false    
  self:GetEntity().collisionEnabled = false    
  self.properties.explosionEffect.active = true
end

Line 10 states that when the player touches the barrel (OnCollision) Crayta should run the code on line 11.

Line 11 makes the mesh invisible by setting it’s visible property to false. 

Linking Properties

When we define a property in a Properties Bag we can then set its value in the Crayta editor. In the Entity Explorer, make sure you have your ExplodingProp selected and you should be able to see that our explosionEffect Property has appeared under our Script

Here you can see that explosionEffect (or explosionEf…) has appeared as a property in the ExplosionScript area in the Entity Editor (bottom right).

Use the dropdown menu next to the explosionEffect Property in the Entity Editor and select Explosion from the menu.

Select your Explosion Effect from the explosionEffect Property dropdown in the Entity Editor for the barrel.

Return to the game editor by clicking on the Game tab. Preview the game and test your code! Hopefully when you now run into your ExplodingBarrel you see a mighty explosion. Great! But does it feel like there is still something missing? It’s a bit quiet for an explosion…it’s missing sound!

Adding Sounds

Sounds are great for adding weight and depth to your game. Using a similar process, we can add sounds to our game world, and make the explosion go “KABOOM”.

Use the Library dropdown to select Sounds. Type the word “explosion” into the Filter box to show only the sounds which include the term “explosion” in the title.

You can filter the Sounds by typing in the Filter box.

You will see that there are a variety of explosion sounds to choose from. To preview a sound, click the preview button. Choose your desired explosion sound and add it to your Explosion entity by left clicking on the entity in the viewport.

Add the explosion Sound you selected to the explosion Effect in your Game World.

With the Sound Entity selected use the Entity Editor to rename the sound ExplosionSound. 

Use the Entity Explorer to make sure your ExplosionSound is a child of your Explosion (this means if we ever move our explosion our sound will stay with it). 

Name your sound ExplosionSound. It should be a child of your explosion Effect.

Tech Tip: Sounds On Location

Sounds are localised in Crayta, so the closer you are to the sound, the louder it is, the further away you are, the quieter the sound is. If a sound is too faint or you don’t know if its playing check the sound position (you can double-click on it in the Entity Explorer to zoom the camera straight there).

If you now preview the level you will find that the sound plays automatically at the start of the level (similar to our Explosion Effect). To stop this occurring, select the ExplosionSound and uncheck the “active” checkbox in the Entity Editor.

Uncheck the active checkbox for the Sound in the Entity Editor.

Playing Sounds

Open the ExplosionScript in the script editor by selecting your ExplodingProp and clicking on the Code Editor button next in the ExplosionScript Entity Editor.

Add a property named explosionSound to your ExplosionScript’s Property Bag. Don’t forget to add the comma on line 5. In Lua you need to separate each item in the Property Bag with a comma.

local ExplosionScript= {}

ExplosionScript.Properties = {    
  { name = “explosionEffect”, type = “entity” },    
  { name = “explosionSound”, type = “entity” }
}

In the OnCollision() function set the sound to active using code. 

function ExplosionScript:OnCollision()    
  self:GetEntity().visible = false    
  self:GetEntity().collisionEnabled = false
  self.properties.explosionEffect.active = true    
  self.properties.explosionSound.active = true
end

This will mean the sound plays. Similar to the explosion, the sound will play when we set the active property from false to true (try toggling the checkbox in the Editor).

Save your script and return to the game editor window. In the ExplodingBarrel’s Entity Editor use the dropdown selector to set the explosionSound Property to the ExplosionSound in your game. 

Your final script should look like this:

local ExplosionScript = {}

ExplosionScript.Properties = {
  { name = "explosionEffect", type = "entity" },
  { name = "explosionSound", type = "entity" }
}

function ExplosionScript:Init()
end

function ExplosionScript:OnCollision()
  self:GetEntity().visible = false
  self:GetEntity().collisionEnabled = false
  self.properties.explosionEffect.active = true
  self.properties.explosionSound.active = true
end

return ExplosionScript

And your game screen should look like this:

Notice that the two Properties in the Script have been set to the Explosion (Effect) and explosionSound respectively. These two Entities have their active checkbox unchecked.

Preview your game. Make sure your sound is turned on and go collect that Exploding Barrel: Kaboom!

Creating A Template

Now that you have made an explosive Mesh, you can turn it into a template to re-use it again and again. To do this, make sure you have selected the top-level entity of what you would like to make a template – in our case ExplodingBarrel is selected.

Select the Entity you want to turn into a Template.

In the Entity Editor click Template -> Create New Template.

Click Template > Create New Template…

I’ve called my Template ExplodingBarrel, but you can name yours something that’s appropriate for you.

Name your Template something memorable and distinct.

Now look over to the Library window and select Templates from the dropdown menu, You can see that you have three items, including our new ExplodingBarrel item.

On the left-side of the screen, the ExplodingBarrel has been added to the Templates section of the Library.

Select your exploding item and add it anywhere in your game world by left-clicking. I’ve created a somewhat difficult situation for my player…

Now you can add lots of exploding barrels!

Summary

Congratulations on completing the first tutorial on coding in Crayta. In this tutorial we covered:

  • Adding game objects
  • Adding scripts to game objects
  • Running code on collision events
  • Using code to affect our game world
  • How to create a template from a group of entities

Whilst it may seem small, with these basic tools we can create a multitude of scenarios. We can use these same tools and techniques to add unique and interesting actions to our game, and make something that people want to play over and over again!

Next Steps

Not done yet? Continue to the next tutorial to investigate triggers, or get creative with what you know already. Why not try:

  • Create a bank door that explodes when you touch it
  • Create a magical axe that disappears amidst a sparkly magical animation when you walk into it
  • Make a bell that rings when you jump on it

Want to keep going? Check out the next tutorial, which looks at Lua in a bit more depth and shows you how to use triggers to commence in-game events: Basic Coding 2: Variables and Datatypes.