Categories
Uncategorized

Uploading images for your game

Overview

You can upload images for your game in the creator companion site, here: https://create.crayta.com/images. There are two categories of images that you can upload – the regular images, shown in the “Temporary image storage” tab, and UI images, shown in the “My UI images” tab.

Regular images are those which can be used as promotional or supporting imagery for your game, such as the game card that players will see on the “Play” page, or the images you see in the details of a game when you select it in the “Play” page.

UI images are images which you can use in the UI (user interface) within your game. For example, you might have an icon for each team in your game that you want to display on the scoreboard, or an image to use as a painting in your in-game saloon.

Uploading images

Head over to the developer companion site linked above to upload images for your games. For regular images, use the “Upload” tab, and for UI images, use the “Upload UI Image” tab.

Make sure your images are less than 1mb in size, and they should be in jpg or png format. When you upload a new image, it will first need to be approved before you can use it in your game. This process should take less than 24 hours.

Any images you upload will appear in your images tab. You’ll see their approval status above – once the image is marked as “approved”, you will be able to use it for your game.

Note that for the regular images, there is a maximum limit of 6 images at a time on the “Temporary Image Storage” tab. These images become permanent when you use them, e.g. when you make them a game card or a promotional image. At this point, you are free to delete them from the temporary storage, and they will remain where they’ve been used.

For the UI images, you are free to upload as many of these as you like, and when approved they will become permanent.

Using images

You can use your approved images in the Create > Games section of the companion website: https://create.crayta.com/games. Select one of your games, and then use the tabs to select a cover image, or supporting images.

Using UI images

Once a UI image is approved, you will be able to use its URL to have it appear in your game. You can find this URL on the “My UI Images” tab. Copy this URL, and then you can paste it directly into Crayta in a widget, or into a script property that will pass it to a widget to be displayed. You can handle this yourself, through the widget HTML directly, or with a combination of widget and Lua code. Alternatively, you can use the Simple Image package, documented here – https://forum.crayta.com/t/simple-image-package/527

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.

Categories
Basic Tutorials

Basic Tutorials 4: Combat

Preface

There is a huge variety of games that aim to achieve a whole range of experiences and enjoyment. The idea of combat in games is a simple, primal addition, but in adding combat to a game a new element of choice is added, and a chance to outwit (and outgun) your friends. 

Combat is quite often a central aspect of gameplay for lots of different reasons, and isn’t always the run-and-gun style that it seems for non-gamers. It can be used to tell a story like in Last Of Us or it can present puzzles like in Legend Of Zelda or Shadow of the Colossus. Combat can also be delivered in lots of different ways as well. For example, Silent Hill’s creepy aesthetic and tense atmosphere or Call Of Duty’s action-packed warzones, or it can be made into a competitive team sport such as in Overwatch, CS:GO or Fortnite, each of which require a team to have excellent communication, teamwork and tactical skills.

Whatever the reason for including combat in your game, there are a few simple techniques that you can use to make your combat compelling and engaging, and to give your players something more in-depth than just point and shoot. Let’s get into it.

Introduction

This tutorial will look at leveraging some of the skills you’ve learned from the previous basic tutorials, and add a premade game type into the mix to put your own stamp on a tried-and-tested game mechanic. It will look at:

  • The “Capture The Flag” game type
  • Adding destructible and indestructible terrain
  • Level editing to create intense battles with guns and traps

Create Your Game

Under the CREATE A NEW GAME menu, find the Team CTF (Capture The Flag) game template. Select this template, and select the Start: Team CTF starter map. Notice that this time we will not be using the Empty Game. Give your game a name, choose a thumbnail image and enter the editor.

Use the Team CTF game template for this tutorial.

Welcome to Capture The Flag!

Before we make any changes, Preview the game by holding D-PAD DOWN. 

You will see that there are two flags, and two coloured zones. Players start in a “Lobby” as they wait for all Players to connect. When the Lobby time limit reaches 0, the game begins.

The object of the game is to capture the opposing team’s flag by running into it, and then bring it back to your team’s coloured zone. Each time you do this, your team will score one point. The team with the most points when the timer reaches 0 wins. If a Player dies, they will respawn at their team’s base. 

The game is quite simple at the moment, let’s mix things up.

End the game preview and ensure you are in Basic Editor mode.

Moving The Bases

This section concerns moving the bases to a different location on the map. If you don’t want to move the bases, and are happy with where they are, you can skip this step, but it’s good practice to fully configure your own game.

A base is comprised of the following Entities:

  1. A coloured floor – This indicates to the player which base is which. The red and blue plastic floors are not destructible, so that the flag is always accessible.
  2. A flag – The flag is a Prop Entity. When a Player collides with the flag they “pick it up” and carry it on their back. To “capture the flag”, the Player with the flag must collide with their own team’s flag in their own base. When they have captured the flag, it is immediately returned to their opponent’s base, ready to be captured again.
  3. A locator – The locator in the base is where Players are respawned when they die. 

To move a base will take three steps:

  1. Create a new floor area which will specify the new base area
  2. Move the flag and respawn locator to the new base
  3. Delete the old floor area

Let’s get started.

Look at the floor and press X to open the Entity Editor. This will show you the Entity Editor for your terrain, and it gives you a good opportunity to see an overview of your map.

You open the Entity Editor for the Terrain and this will give you a good overview of your level map.

Open the Entity Editor for the Terrain regularly, to get an overview of how your level is shaping up. For now, press B to exit the Entity Editor.

Press Y to open the Library. Navigate to the Voxels tab. Highlight the Plastic Dull voxel and press A. You will see that you have a choice of colours of Voxel to add to your Hotbar. This game has been setup to use Red and Blue, so stick to these colours for now. Highlight either the Red or Blue Plastic Dull Voxel and press A to add this Voxel to your Hotbar

Locate the Plastic (Dull) Voxel and press A.
Add the red or blue plastic Voxel to your Hotbar.

Use D-PAD UP to change the Voxel tool to a 1x1x1 block

Change your Voxel tool to a 1x1x1 block.

Press R2 to place a Voxel and create a new base somewhere else in the level by drawing a low platform. I have chosen to position the bases in each corner of the map. Do this for both the Red and Blue teams.

When you have finished, press RB to select an empty Hotbar slot. Look at the floor and press X to open the Terrain Entity Editor again. You should see you now have two bases on your map – the original two, and two new ones.

You should now see 4 bases marked on the map. The old ones, and the new ones you have added.

Press X to close the Entity Editor.

Now you need to move the flags onto your new bases.

Move towards a flag and, whilst looking at it, press X to open the Entity Editor.

You should see that the flag entity has a flagSpawnerScript attached to it. Each flag has a different team. By default, Team 1 is on the Blue floor, Team 2 is on the Red floor.

You have two options to move the flag. You can pick the one that suits your style of level making:

Option 1: Numerically Move The Flag

You can edit the position data in the Entity Editor for the flag. This method is better for level designers who like to be very precise.

To do this, ensure the Entity Editor for the flag is open. Use the D-PAD to navigate to the “position” property box. These three numbers represent the coordinates of the flag, and specify its position in the world. Adjusting the first two boxes will move it’s position on the ground, whilst the third box changes it’s vertical position.

Use the position property boxes on each flag to move them to the corresponding team base. To do this, highlight one of the first two position property boxes and press A. Use D-PAD LEFT/RIGHT to change the numbers and move the flag.

If you hold RB whilst pressing D-PAD LEFT/RIGHT you can increment the numbers in multiples of 10, and move the flag faster.

Move the flags to the new team bases.

Press A to finish editing a property box. Press X to close the Entity Editor when you are happy with the flags position.

Option 2: Pickup The Flag

Alternatively, you can pickup the flag and move it to a different location. This method is better for freeform level designers.

Look at the flag with the Entity Editor closed, and press RT to pickup the flag. Head over to your new base location, and place the flag by pressing RT again. If you want to cancel the move and return the flag to it’s original position you can press RB (this also selects an empty slot on your Hotbar).

Once you have moved the flags to new bases, the last Entity to move is the Locator, which is the spawn point for the Players on each of the teams. Use the same technique you used to move the flags to move this Locator.

Open the Entity Editor for each flag and make sure that Team 1 is on the Blue floor, Team 2 is on the Red floor. Close the Entity Editor.

The last step is remove the old bases. To do this, you can paint the red outline of the base with the Technical Grid Voxel.

Press Y to open the Library. Navigate to the Voxels tab and add the Technical Grid Voxel to add it to your Hotbar. Close the Library.

Press D-PAD UP to cycle through the Voxel tools until you see the Fill tool. Press R2 to use the Fill tool on the previous base outlines.

Use the fill tool on the old bases to remove them.
Once you have moved your bases you will have a larger combat area.

Adding Walls

To make a more compelling level it is a good idea to add some walls so that the opposing teams can’t just stand and shoot each other. You can use Voxels to create obstacles on your map, which players can use to hide behind, or which cut off certain routes to the opponents flag. This “cover” also creates opportunities for teams to outflank (and outwit) each other. 

Choose a Voxel to be your walls. The walls are destructable by default, so select a Voxel that is usually considered destructable in shooting games. Press D-PAD UP to increase the size of the Voxel tool, and use large blocks to create a general shape to your level. You might find it easier if you double jump to enter flying / non-clip mode. 

Try to compose a variety of spaces. Create some wide corridors and some narrow corridors, some small areas, and some bigger areas.

You can choose if you want to surround your level perimeter with a wall. If you choose not to have a wall then if your players fall off the side they will fall to their doom.

Mark out your level and create a variety of cover with the Voxel tools. Don’t worry about detail for now.

Remember you can get an overview of your level by opening the Entity Editor for the Terrain.

Creative Control: Combat Situations

Your level should offer rich opportunities for players to battle in a variety of ways You could choose between short, medium and long-range combat situations or a mixture of all three. 

Creative Control: Level Design

There are lots of ways to design a level. You could use a pen and paper to sketch some ideas for your level, or build structures freeform in Crayta’s EDIT mode, and devise a level bit-by-bit. It’s your choice! 

Think about how your level could be structured. Make sure to include points which might be suitable to spawn resources such as different guns.

Also consider whether there might be perilous areas of your level, traps that either team can take advantage of to gain the upper hand. 

Once you have given your level a general shape, you can tweak some of the spaces by adding and removing smaller Voxels to give opportunities for more or less cover in certain areas. Experiment with different sizes of the Voxel tools.

Start to add detail with smaller groups of Voxels, and give your level some interesting spaces.

Creative Control: Game Balance

Remember there are two teams on the field of battle at once, so try to keep in mind how to make sure that the game is fair for both sides. Try to give each time an equal number of good positions, and build in weaknesses to dominant areas of the map to encourage teamwork and tactical thinking.

Indestructible walls

Preview your game. If you shoot any of the Voxels you placed then you will see they are destroyed. If you shoot either the Red or Blue team floors, you will notice that they are indestructible. This is a good thing, because otherwise a team could destroy their own floor and the flag would no longer be accessible, ruining the game.

You can turn off destructable voxels by looking at the floor anywhere and unchecking the “damageEnabled” property.

As you will be adding a mixture of destructable and indestructable cover you should leave damageEnabled checked.

Creative Control: Destructible Environments

Having destructible cover is great for forcing players to think on their feet, and adjust their tactics in the middle of a gunfight, but having indestructible areas can make map control more important to achieve victory.

You can create your own indestructible Voxels.

Press Y to open the Library and choose a Voxel that is unlikely to be damaged, for this tutorial we have used Metal Steel. Build some cover in your game using the Metal Steel Voxel.

Build some metal walls that will be indestructible cover.

Once you are happy with your indestructible cover, open the Entity Editor for the Terrain.

Look at the floor and press X to open the Entity Editor for the Terrain.

At the bottom of the Entity Editor is a button “Add to Entity”. You can use this button to add Scripts and UI Widgets to an Entity. Highlight Add to Entity and press A.

Click the Add to Entity button add the bottom of the Terrain Entity Editor.

Select Add > Script > voxelHealthScript.

Select Add > Script > voxelHealthScript.

The voxelHealthScript allows you to tell Crayta how much damage different Voxels can take before they are eliminated. You can also set a default value here.

Now, use the Add to Entity button again to add the voxelHealthValueScript.

This Script enables you to determine the health of a specific voxel (how much damage it can take before it is eliminated). Once you have added it to the Entity Editor select Metal (Steel) Voxel in the voxel dropdown, and set the health to 0 (use LEFT D-PAD to reduce the value).

Select Metal (Steel) and set the health value to 0.000.

Press X to close the Entity Editor. Hold D-PAD DOWN to preview the game and test that your Metal Steel is indestructible by shooting it.

Try shooting the Metal (Steel) Voxels. Notice how the steel voxels do not get damaged by bullets.

Edit your level so that you have a mixture of destructible and indestructible cover and remember to play test it regularly so that you can see how your level editing changes the dynamic of the game.

Creative Control: Voxel Health

A voxel doesn’t have to be destroyed in one shot. Just like we decreased the Voxel Health to 0.000 to make it indestructible, you can increase the Voxel Health to take 2 bullets, or 10 bullets! The Automatic Rifle default damage is around 150, so a Voxel Health of 150 or less would take one shot (1 bullet x 150 damage = 150), 300 or less would take 2 shots (2 bullets x 150 damage = 300) and so on.

More Guns Please

You can find many different weapon packs by visiting the Store in the Library.

Press Y to open the Library. Press Y again to open the Community tab. Find the Shotgun Package within the store, highlight Install and press A to install the Package.

Return to the Library by navigating back to the Library tab, and open the Templates.

You should see a new template has been added to your Templates, called Shotgun. Select the Shotgun Template from the Library and place it in your scene.

Open the Shotgun Entity Editor and find the pickupSpawnerScript Properties. Chane the Properties to match the following:

Change the highlighted Properties on the pickupSpawnScript attached to your Shotgun.

After making these changes, navigate to the top of this Entity Editor and make sure to select Copy To Template.

Copy To Template means that when you place another Shotgun somewhere else in your game it will keep the same pickupSpawnerScript Properties.

Preview the level to try the Shotgun. Walk over the gun to pick it up.

Preview the level. Pickup the Shotgun and blast some stuff.

Return to the game editor.

You can switch between the guns in-game by pressing RB and LB.

You may disagree with some of the values of the Shotgun (does it cause too much damage? Is it too accurate?). You can fully customise each gun to behave differently by using the Entity Editor and changing the Properties on the gunScript. Remember to press Copy To Template after making any changes.

Press Copy to Template to update the template of this gun and make the changes take effect.

Creative Control: Risk and Reward

Based on your experience with the new guns, consider where might be a suitable place to put them in a level. You may decide that the base of each team has a library of weapons available, or that one team has only shotguns whilst the other have only handguns. 

Alternatively, you could put less powerful guns in easy to reach places, and more powerful guns in dangerous places, such as the middle of a crossfire, or somewhere requiring serious parkour skills. 

Adding this risk and reward can give the game more depth, as the teams will need to weigh up arsenal resources versus the risks to team members, and ultimately decide which will help them win the game.

Level Peril

What’s more exciting than two factions battling it out in intense combat? When that combat takes place in a hostile environment. Sometimes, it’s the situation that can turn the tides of battle, and teams can use natural dangers to their advantage, as distractions or as danger themselves.

Open the Library and press Y to navigate to the Community. Find and install the Basic Combat Traps Package. Return to the Library and add the Laser Spikes Template to your Hotbar.

Place the Laser Spikes somewhere in the level. Remember, you can rotate the Entity to make laser walls also.

You can also try placing multiple Laser Spikes, and creating no-go areas or dangerous corridors that are asking for escalating gun battles. Players can shoot through the Laser Spikes, but can’t get past them, so they can offer some exciting advantages to clever Players. 

Players can shoot through Laser Spikes, but can’t travel through them.

Preview your game. Test the traps. You should find that they cause your player damage. 

Return to the EDIT mode.

Touching the Laser Spikes will cause players damage, and knock the player back. You can change the amount of damage and knockback that the traps have. In EDIT mode, open the Laser Spikes Entity Editor. The properties that can change the damage that the Laser Spikes cause can be found in the passiveDamageScript properties. 

Using the Entity Editor, you can change the amount of damage caused to the player, how much it knocks the player back, and what Sound effect will play when a player collides with the trap. 

Experiment with the properties of the Laser Spikes, and adjust them to suit your game. You can make a trap deadly, by increasing the localDamage to 1000! You can also change the Mesh Asset to suit your theme. Maybe your game features a highly lethal coffee table, or a not very dangerous banana which launches players across the map.

Turn your laser spikes into a dangerous art-deco coffee table if you like.

Recap

Congratulations on completing the last of the Basic tutorials. In this tutorial, you have discovered:

  • Remixing your own version of a Capture The Flag game
  • Designing a level for exciting and dynamic combat
  • Adding destructible and indestructible terrain
  • Adding guns to a level
  • Adding traps to a level

Adding Polish

You have started designing a level for combat, but there are endless opportunities for changing the environment in your game, and making a really exciting and challenging level with plenty of opportunities for strategy.

Using the level you have started, you could try and include some of the following ideas:

  1. Improve the theme of the game to start building a sense of story. Why are these teams fighting? Why do they need to capture the flag? Even the most combat focused shooting games have some kind of narrative.
  2. Try making your level have high areas and low areas, and experiment with three dimensional tactical advantages.
  3. Install the Super Smash ‘n’ Grab package, and place the flags in Bank Vaults, with their own key. Now Players will need to find the key, or blow open the doors before they can start to win points.
  4. Give your game level more variation by adding some of the premade Mesh Assets that fit your theme. You can also turn on physics on the Mesh Assets, which means that players can move them around and give themselves more cover or hiding spots.

Next up: Advanced Editor Mode

Congratulations on completing all of the Basic tutorials. Hopefully you feel inspired to experiment with some of the other game modes, and get creative with the tools at your disposal.

To really take things to the next level, you can try the Level Editor in Crayta with a keyboard and mouse. In the Advanced Level Editor you will have an opportunity to code within Crayta and use scripts to customise the interactions in your game.

 There are a variety of guides which you can use as a reference point for using some of the Advanced tools in Crayta.

Familiarise yourself with the Advanced Level Editor in the Advanced Workflow Tutorial.

Learn some basic scripting in the step-by-step Code Tutorials.

Categories
Basic Tutorials

Basic Tutorial 3: UI

Preface

Until this point, the tutorials have focused on creating gameplay that is possible within Crayta, and have not really considered the game objectives. I believe a game without an objective is more like a toy, although if you really want to geek out about the definitions of play, games and toys, checkout Chapter 3 of Jesse Schell’s The Art of Game Design: A Book of Lenses.

In order for you to give your players an objective, there needs to be a way of communicating to the player how close, or far away, they are from reaching the objective, and notify them when they have successfully accomplished the objective (or plummeted to their death). This is when the UI (user interface) and HUD (head’s up display) come in handy.

Introduction

Firstly, let’s clarify the different terms that we are using.

Heads-Up Display

The HUD describes the graphics and text that are overlaid on the game screen, usually to communicate the current state of the game to the player whilst they are in the middle of playing the game.

User Interface

The UI is a term often used in game design to describe all the interaction and information exchange that occurs between the player and the game. It’s primarily concerned with the menu systems, although it’s occasionally used as an umbrella term to talk about the HUD as well.

This tutorial will focus on creating a game with a “Heads-Up Display” to add depth to a game level. Adventure games such as “Temple Run” or the “Uncharted series” often require the player to overcome obstacles, preferably without dying and sometimes under time-pressure. These are aspects of the game that need to be communicated through a well placed HUD, so for this tutorial, we will be making an adventure game!

If this is your first time using Crayta, we recommend starting from the first tutorial in this series of basic tutorials. Otherwise, let’s get started.

Create Your Game

Create a new Empty Game and call it “ Danger Dash”. 

The objective of Danger Dash is to race through an obstacle course, dodge the hazards and reach the end before the timer runs out. 

Open the Library (Y) (or ‘L’ on keybaord) and change to the Community tab (Y). Find and install the Package “Danger Dash”. If you have any difficulties with this step, revisit the Packages tutorial to get a rundown on installing Packages in Crayta (found here: Basic Tutorial #1: Packages).

The “Danger Dash” Package gives you everything you need to make a classic adventure game with a modern twist. 

Winning

This tutorial follows a similar pattern to the puzzle game made in the previous Events tutorial, by starting with how the player wins, and working backwards to add difficulty to that journey.

To win, the player must interact with an instance of the “Battlestation”  (also called a desktop PC) that is in the Package. You will start by adding the Battlestation to the game world.

Open the Library again (Y) and use Right Trigger (RT) and Left Trigger (LT) to navigate to the Templates tab. Use the D-PAD to highlight the Battlestation Template. Press A to add it to your hotbar, and press B to close the library.

Add the Battlestation Template to your Hotbar.

Place the battlestation in your game world (RT) a little way away from where the player starts (to make space for obstacles and other exciting level features).

Place a Battlestation in your game world.

Preview the game by holding D-PAD DOWN. 

Walk your character towards the desk. Interact with the PC by pressing X. You should see a textbox appear. Congratulations! You win.

The win screen – the object of Danger Dash is to get to the computer.

This textbox is a user interface entity, called a Widget. Widgets can be used to communicate a variety of information to the player as you will discover in this tutorial. This Widget requires the user to press Close before it will be removed from the screen. Close the Widget by using the thumbstick to control the mouse and click the button by pressing A.

Exit the game preview and return to EDIT mode by holding D-PAD DOWN. 

Tech Tips: Chain of Events

It is not immediately clear how this works, so this tech tip aims to break down exactly what is going on.

There is a script attached to the ‘computer1’ Entity (a child of the Battlestation Entity) which displays the textbox and updates the text. In EDIT mode, look at the computer and open the Entity Editor by pressing X.

This Entity has a ShowWidget script, which can be used to show and hide Widgets

When a Player interacts with the Entity, the OnInteract Event is fired, and calls a function within the ShowWidget Script that updates the textbox and makes it visible. You can see this function in the Entity Editor next to the OnInteract dropdown.

This chain of events happens very quickly, and results in the textbox appearing. Behind the scenes, there is a series of logical steps which are:

Creative Control: Tell A Story

We can use this same Entity in lots of different ways by changing the mesh. It is also possible to change the text displayed if you use a keyboard, which means we can add lots of story elements to the game world.

Try creating a narrative that the player can discover by interacting with different entities. Do you want players to read your messages in any order, or is there a path you want them to take?  Get creative, and play with your level design to direct players to specific points of interest. 

Let’s make this game a bit more difficult.

Adding HUD Widgets: Health

Widgets don’t have to only appear when the player interacts with things, they can be always onscreen and form the HUD. 

Open the Library, navigate to the Templates tab and add the PlayerHealthLocator to your Hotbar. Close the Library.

Add an instance of the PlayerHealthLocator Template anywhere to your game world.

When you add PlayerHealthLocator, you should see that only a Locator icon appears, without a Prop or any kind of physical object.

Tech Tip: A Locator Entity

The PlayerHealthLocator template is comprised of a Locator with some Scripts attached. 

A Locator is a type of Entity that doesn’t have a Prop or Sound or any physical body. A Locator represents a single point in the game world and can be used to specify a position, such as where the player will spawn. 

We are using a Locator here so that we can add a Script that affects the game world without requiring a physical Entity. This is essential for us to be able to add HUD elements without using the Advanced Editor.

The Script that is attached to PlayerHealthLocator runs automatically when the Player starts the game, and add the Health widget to the Player’s view. To view the Widgets that are attached to the PlayerHealthLocator, look at the PlayerHealthLocator Locator icon and open the Entity Editor by pressing X.

Open the Entity Editor for the PlayerHealthLocator.

Two textboxes appear on the screen. The Health Widget in the top-left corner, and the Game Over Widget in the center of the screen.

The Game Over Widget will only appear in the game when the player’s health reaches 0. 

The Health widget shows the players health and remains visible throughout the game. 

It is possible to change the starting health value next to the “health” property in the basicPlayerHealth Properties in the Entity Editor by navigating the Entity Editor in the normal way. In this way we can give the Player more or less health, and make the game harder or easier. For now, leave this value as 100.000.

You can change the value of a player’s health using this property.

Press X to close the Entity Editor.

Tech Tip: Clients and Servers

Crayta is a multiplayer game, which means that there can be more than one player in the game world at any time. As such, the game needs to be synchronised so that events happen for all the Players at the same time. For example, if you blow open a bank door, the same door should blow open for all the Players in the game at the same time.

To synchronise the game for all the Players, the game runs on a server, which is a computer somewhere in the world that is connected to the internet. A Player’s Stadia instance is called a client

The Crayta Servers manage the communication between the clients to ensure the game stays consistent for all players.

Whenever a Player does something in the game, the client sends that information to the server. For any event, whether caused by a Player or an Event in the game itself, the server sends the updated game information to all the clients and the game remains synchronised for the Players. 

To make a unique Health Widget for each Player, the basicPlayerHealth Script keeps track of the health values of each of the Players.

Preview the game by holding D-PAD DOWN. You should see the Health Widget now appear in the top-left corner of your screen.

Adding Hazards

So far so good, but the Health system won’t do anything unless there is some kind of peril which impacts the players health. We will use the perilous DamageEntity Template lurking in the Library to make this game a bit more dangerous. Open the Library, navigate to Templates and add the DamageEntity Template to your Hotbar

Place the DamageEntity in your game world, as an obstacle between the player and the Battlestation.

Place the DamageEntity between where the player starts and the Battlestation.

Open the Entity Editor for the DamageEntity you have just placed in your game world.

The DamageEntity Template has two scripts attached; 

  1. The RotateAndMoveScript which is covered in the Packages tutorial: Basic Tutorial #1: Packages 
  2. DamagePlayerScript, which affects the health of the Player’s Character. The amount of damage caused by this Entity is editable by changing the value next to Damage in the DamagePlayerScript Properties.
You will need to set the player health locator in the properties as playerHealthLocato

At the moment our DamagePlayerScript has some missing information, as shown by the warning symbol:

The warning symbol tells us that some information is missing or incorrect.

This is telling us that the DamagePlayerScript does not know who to notify about the damage information. Click the down arrow and set it to World->Terrain->playerHealthLocator1.

Use D-Pad + Right to expand the World and terrain and select PlayerHealthLocator1.

Preview the game and test the DamageItem by walking into the circular saw.

Ouch! You should see your Health reaches 0 (rather quickly) and the Game Over Widget appears.

You may notice that the circular saw is spinning the wrong way, it doesn’t move, and it is still quite easy to reach the Battlestation. Open the Entity Editor for the saw, and make the saw spin in the correct direction. You can also try making it move, and bounce, using the other properties in the RotateAndMoveConfig Properties to make the obstacle more challenging.

Upping The Ante

Once you are happy with the movement and rotation of the saw, duplicate the DamageItem Entity, and move it to a separate location. Change the values in the RotateAndMoveScript Properties to alter the speed and direction of the different saws. Use the voxel tools to create a room and force the Player to run a gauntlet of circular saws to reach their goal.

Hard mode: ENGAGED.

Creative Control: Peril

Remember, you can also change the mesh of the saw, to make different dangerous items, and edit the level to theme the game in any way you like.

Adding A Timer

Just in case a multitude of spinning wheels of death isn’t enough, you can give your Players a bit more pressure by adding a ticking clock.

Open the Library, and add the TimerLocator Template to your Hotbar. The TimerLocator is another HUD item based on a Locator.

Add this to the game world at any location.

The Timer Widget will display the same countdown for all Players in the game. The Widget is already set to be displayed to everyone, and will be added to each Player’s screen when they start the game.

You can edit the number of seconds on the timer by changing the Length value in the SimpleTimerScript Properties. 

Change the TimerScript Length Property from 100.000 to 10.000.

Preview the game and allow the timer to run out.

After changing the duration of time for the Timer to 10 seconds you should see the timer count down 10 seconds at the top of the screen.

The timer completing doesn’t cause any game actions. This is something you need to rectify.

Exit the game Preview mode and open the Entity Editor for the TimerLocator once more.

In the TimerScript Properties you can see that the OnComplete field is empty. This means that nothing happens when the timer reaches 0:00. For this game, when the timer reaches 0:00, a Game Over message should be displayed. There is a Game Over Widget already attached to the PlayerHealthLocator, and the ShowWidget Script has the functionality you need to show the GameOver Widget, you just need to hook it up to the OnComplete Event. 

Use the “+” next to OnComplete to set the Entity / Script / Event that performs this action.

Set the Timer’s OnComplete Event Listener. Select the PlayerHealthLocator Entity. Set the Event to the ShowGameOver() function on the basicPlayerHealth Script attached to the playerHealthLocator.

Press X to close the Entity Editor. Preview the game and allow the timer to reach 0:00.

Preview the game and allow the timer to reach 0.00

You should see that when the timer runs out, the Game Over Widget is displayed. Great! You can make Widgets appear and disappear like this as long as there is an associated Script with the appropriate functionality. 

Return to EDIT mode. Set the TimerScript duration Property to 100.000. Test your game to ensure that the level is possible. Tweak the damage caused by the DamageEntities and the TimerScript duration to achieve a good level of difficulty.

Stopping The Timer

The objective of this game is to reach the Battlestation before the time runs out, and without our health reaching zero. So far the game meets these requirements, although the timer continues to countdown even if we get to the computer in time (and results in showing the Game Over Widget when the timer runs out). The timer needs to stop when we interact with the Battlestation.

Make sure you are in EDIT mode and open the Entity Editor for the computer1 by looking at the Battlestation computer. Add the StopTimer function as an additional Event Listener to the onInteract Event on computer1. You can find it on the TimerLocator Entity on the TimerScript Script.

Add StopTimer() as an additoinal OnInteract event.
Add the StopTimer event to the onInteract event on the Battlestation.

Preview the game and test that reaching the computer stops the time and shows the the winning Widget. Great work!

Hacking the computer before the time runs out!

Recap

Well done! You’ve successfully completed this tutorial and made a bonafide adventure game. In this tutorial you have looked at:

  • The difference between a UI and a HUD
  • A popup Widget that appears when you interact with something in the game world
  • The difference between the Client and the Server
  • Player health 
  • Dangerous items that can hurt the player
  • Timers and timer events that add time pressure to the level

Adding Polish

Now that you have mastered the basics of adding UI elements to the game world, and how they can be used to display different types of information to the Player, you can take these ideas further to add more depth and excitement to your game. Here are some possible activities you could try to explore the UI in more depth:

  1. Add a Battlestation to the start of the level. Remove the Story widget, and start the timer when the Player interacts with it – you will need to uncheck the Autostart Property of the TimerScript.
  2. Make the game a Banana Run game where the Player must dodge bananas.

As you can see, there are even more possibilities now that you have Packages, Events and Widgets at your disposal. These tools can be combined in lots of different ways, and make Crayta a very versatile and comprehensive game engine.

Next up: Putting It All Together

Now that you have got to grips with some of the fundamentals of the Crayta editor your games can start getting a even more exciting. The next tutorial will looks at extending a ready-made Capture The Flag level, and turning it into a intense warzone. Hold onto your guns, we’re introducing COMBAT.

Basic Tutorial 4: Combat

Categories
Basic Tutorials

Basic Tutorial 2: Events

Preface

Every game needs user interaction. Without interaction, games lack their most powerful ingredient – player choice. In this tutorial, we will start to add more interactivity to our games using an event-driven system. 

In the context of a game, an Event could be anything that changes in the game world. It could be the user pressing a button on their gamepad, a countdown timer reaching zero, or two enemies colliding. There are three main types of Event :

  • User interface – the user has interacted with something in some way.
  • Timer – a timer has reached a value.
  • System – an embedded system (such as the physics engine) has fired an event.

When an Event occurs in our game, we can use that event to cause a reaction. This tutorial will be focusing on adding functionality to our game that causes a response to an Event, and changes the state of the game.

Introduction To Puzzle Games

Puzzle games can be as elaborate and exciting as you like. They can be made more complicated by giving obscure clues and adding layered objectives, or easier by giving more clues and reducing the number of objectives.

For example, a puzzle game could be as simple as “Open the door”, where the user just opens a door. Or it could be a bit more complicated. For example, if the door needs a key, but the key is locked in a vault, and to get in the vault you need the code which is written on the inside of a teapot which you need to smash with a hammer, but the hammer is positioned a bit too high to reach so you need a box to stand on…you get the picture.


An example of an easy puzzle game. The player has one simple puzzle that stands between them and the objective.
A more difficult puzzle game would have several puzzles between the player and the objective. You could also increase the difficulty of the puzzles, but make sure the player can still solve them!

This tutorial will guide you through making an easy puzzle game, and then add more obstacles to make it harder.

Create Your Game

Create a new Empty Game and call it “Super Smash-n-Grab”. 

When you enter the game, open the Library by pressing Y

Press Y to open the Library and press Y again to open the Community tab. Find and install the Package “Super Smash-n-Grab”. If you have any difficulties with this step, revisit the Packages tutorial to get a rundown on installing Packages in Crayta.

Navigate to the Store, and install the “Super Smash-n-Grab Package.

The SuperSmashNGrab Package gives you everything you need to make a simple heist-themed puzzle game.

First you need to add your bank vault. Open the Library (press ‘Y’ again), use R2 and L2 to navigate to the Templates tab. Use the D-PAD to highlight the Bank Vault Template.

Press “A” to add it to your Hotbar

Add a BankVault Entity to your game world.

Close the Library by pressing “B”. Add an instance of the bank vault Template to your world. Find a good location and press R2 to place it. Press RB or LB to select an empty Hotbar slot to make it easier to navigate the scene.

Gaining Entry: Unlock The Door

By default, the door of the Bank Vault is locked. Before we Preview the game we need to unlock the door and then link the keypad to the door to be able to open it.

Start by looking at the door, and open the Entity Editor by pressing X. If you navigate to the bottom of the Entity Editor you can find the Script: LockedDoor Properties.

Aha here is the first problem. You can see that the “locked” Property is checked, which means the door is currently locked. Uncheck the locked checkbox.

Open the Entity Editor for the Bank Vault door.
Uncheck the “locked” Property checkbox.

Preview the game by holding the DOWN D-PAD.

Interact with the keypad next to the door by looking at it and pressing X. The door should swing open.

Interacting with the keypad should make the door swing open.

Seems pretty easy to get in the bank vault, right? This is because the door is unlocked by default. Let’s turn up the difficulty of this puzzle game. Return to the game editor by holding DOWN D-PAD.

Adding An Obstacle

In Edit mode, look at the door and press X to enter Entity Editor.

Edit the Properties of the vault door.

Make sure you are editing the door by checking the name at the top of the Entity Editor – it should be “BankVault-VaultDoor”. Return the Locked Checkbox to its Locked state by highlighting the box and pressing A.

Lock the bank vault door again.

You have just created a puzzle. Now we need to give the player a way to solve it!

Gaining Entry: Detonation

This tutorial will cover blowing open the door with TNT first, and then using a key to open a different door. 

Creative Control: Player Choice

Games like Hitman and Metal Gear Solid strive to have multiple solutions to each problem. Giving your player choice forces them to decide, makes the journey more interesting and makes the game feel less linear.
Jam some other ideas on other ways to get past a door. For example, you could use the voxel tools to create a hidden tunnel under the vault, or add a keycard that unlocks the keypad, or you could blow the door open with TNT! The only limit is your imagination (and, let’s face it, physics). 

Open the Library and navigate to Templates.

Open the Templates tab.

Switch to an empty slot on your Hotbar and add the TNT Template to your Hotbar.

Place the TNT on the door of your bank vault.

Put some TNT on your bank vault.

Open the Entity Editor for the TNT and change the position and rotation Properties to fine tune the position of the TNT. It should be flat against the door.

Fine-tune the rotation and position of the TNT.

Open the Library again and open the meshes tab. Add the TNT Plunger to your Hotbar.

Add the TNT Plunger Template to your Hotbar.

Place the TNT Plunger nearby, so you can see the door when you press the plunger. 

Place the TNT Plunger a short distance from the vault door.

Preview your game and make further adjustments as required.

If you try interacting with the plunger in Preview mode you will find that nothing happens. This is because we haven’t told the TNT Plunger to listen to any events yet. We need to tell the TNT Plunger what to do when the user interacts with it, otherwise nothing happens. Return to edit mode and we will do just that.

Tech Tip: Events Terminology

Listening, triggering, handling…these are terms used by game developers to discuss Event systems. Using the correct names is super useful when you need to communicate your vision to other members of your game development team.

Event trigger/ Event fire: When an event occurs, we say that the event has “fired”. The thing that caused the event to fire is called the “trigger”. 

Event handler: The code that is executed due to an Event being fired is called an “Event handler”. 

Event listener: An event listener links an Event Handler to an Event. In some game engines we would need to write this in manually, but Crayta manages our Event listeners for us. 

In edit mode, look at the TNT Plunger and press X to open the Entity Editor

Edit the TNT Plunger Properties in the Entity Editor.

Use the D-PAD to navigate to the bottom of the Entity Editor to find the onInteract Property.

Crayta Entities automatically listen out for events that might affect their state in the Game World, such as colliding with another Entity or the player interacting with an it. You can make things happen by adding functions to the event property boxes. 

There are 2 possible events that we can listen for on the TNT Plunger:

  • onInteract: The player looks at this entity and presses X
  • onCollision: The player’s character touches this entity

Tech Tip: Functions

A function is a chunk of code with a single identifier. Programmers group chunks of code into functions so that they can be re-used easily, and to help organise the code into a logical pattern. A single script can have multiple functions. 

A function identifier will usually describe the intention of the code within the function. For example, a function with the identifier “makeInvisible()” should make an entity disappear, a function with the identifier “explode()” should make an entity explode. To run a function, we “call” it.

For example, here is the function within the LockedDoor script which “destroys” the door:

function

LockedDoor:DestroyDoor() self:GetEntity().collisionEnabled = false self:GetEntity().visible = false

End

If you read the code above, it states “for the entity this is attached to, make collisionEnabled false and visible false”. What this means, is that the collisions are disabled and it is made invisible. This is a simplified way of removing an entity from the game. It’s not the most optimal way, but completely destroying an entity comes with other programming responsibilities that are beyond the scope of this tutorial. 

Use the D-PAD to highlight the “+” next to onInteract and press A. Now, highlight the box with the placeholder “(…)” and press A again. 

Add an event handler to the TNT Plunger’s Interact Event. Select the “+” next to onInteract.

You will see three new property boxes appear; Entity, Script and Event. We will use these properties to target a specific entity, target a script attached to that entity, and choose a function within that script. 

Highlight the Entity field and press A. This will display a list of every entity in your scene. 

Pressing A on the Entity Property dropdown will display all of the Entities within your Game World.

Tech Tip: Parents and Children

An Entity in Crayta could be a Mesh, a Voxel Mesh, a Sound or any other item that is added to your game. 

When you add an Entity to your game, Crayta will make it a “Child” of another Entity so that it is attached to something in your game. 

For example, a table is added to the game. Then a cup is placed on that table. Because the cup is on the table, Crayta will add the cup as a child of the table. Then, if we move or rotate the table, the cup will move or rotate with it.

Parent/child relationships exist in most game engines, and are shown using lists:

  • World
    • Terrain
      • Table
        • Cup
      • House
        • Door
        • Television

When we added our TNT to the door, Crayta renamed it to tNT1, so that we can distinguish between that specific TNT, and any other ones we might add to our game later on. 

To find tNT1, press DOWN D-PAD to highlight the Terrain Entity. Press RIGHT D-PAD to expand the list of children added to the Terrain Entity. Do the same with BankVault and you should see BankVault-VaultDoor. Continue expanding the lists to find tNT1. In this tutorial, the tNT1 was here:

Use the dropdown menu to find the TNT Entity you placed on the vault door.

World > terrain > bankVault1 > BankVault-VaultDoor > tNT1

Highlight tNT1 and press A

When you select the TNT, the Event Property should automatically fill with the tntDetonator Script.

Our TNT only has one script attached to it, so the Script Property is automatically filled with our tntDetonator script. If there was more than one, we could use this box to determine the exact script.

Finally, highlight the arrow next to Event and press A. You will be given the choice of two functions that exist in the tntDetonater Script; Detonate() and Init(). Select Detonate().

Press B to close the Entity Editor. You have now hooked up the TNT Plunger to run the Detonate() function on the TNT that is attached to the bank vault door.

Preview your game.

During the game Preview, interact with the TNT Plunger by looking at it and pressing X. You will notice that the TNT detonates, as expected, but the door to our bank vault remains firmly locked. We can fix that by adding another Event Listener onto the TNT Plunger’s onInteract Event.

Return to Edit mode, open the Entity Editor for the TNT Plunger once again. Navigate down the Properties and press the “+” next to onInteract, underneath the previous function we added. Using the same method that we used when adding the Detonate function, add the following function:

  • Entity: bankVaultDoor
  • Script: LockedDoor
  • Event: DestroyDoor()
Select the “+” under onInteract to add another event listener.
Select the BankVault Door and choose the Script: LockedDoor and the DestroyDoor() function.

You should now see two items in the onInteract field; tNT1 / tntDetonator and BankVault-VaultDoor / LockedDoor.

Preview your game again and interact with the TNT plunger. You should find that the TNT explodes, and the door is destroyed. ACCESS GRANTED.

Preview the game, and blow open the door with TNT.

We can add as many functions as we like to this event listener, or to the other event listeners. If you choose to program your own functions you can use this Event Property to make them run.

Gaining Entry: Unlocking The Door

So far we have a bank vault where players can gain entry through the use of explosives. Great! What happens next? Well, usually once you have got the goods you need to escape without getting caught. We are going to use a new instance of just the Vault Door to create another obstacle. This obstacle will get in the way of the player escaping.

Add a different door Mesh to your hotbar and add it to the Game World.

Add door from the Meshes Library to your game world
Build a bank around your bank vault and vault door.

Now your player will have to gain entry into the bank first, then the vault and then escape out of the building.

Creative Control: What’s Your Game About?

This tutorial covers adding two doors, but you can use the same techniques to add more doors, change the scenario and change the direction of the game. 

For example, the player could start in a dungeon and have to escape a castle, or rescue someone from a prison. Requiring obstacles to be solved in different ways keeps your players guessing and makes the game more interesting. Get creative!

Don’t forget you can change the Mesh Asset Property of a Template. So you could change the bank vault door to a jail cell door, or a door to a townhouse.

In Edit mode, open the Library and add the Keycard Template to your hotbar. Then close the Library

Add the Keycard Template to your Hotbar.

Place the keycard in your game world. Preview your game and adjust the position of the Keycard using the Entity Editor if necessary.

Creative Control

You could place your keycard somewhere obvious, or you could place it somewhere devious. You could also consider where someone might leave a keycard by accident, such as on a table (look in the Meshes tab in the Library for inspiration). If you’re more of the trickster type, be sure to give your player clues so that they don’t get frustrated!

Return to Edit mode and open the Entity Editor for the Keycard.

At the bottom of the Entity Editor you will find a script attached to this Entity; HideShowScript. The next step in this tutorial will show you how to use the Event Properties to unlock the door and make the keycard disappear, simulating that you have picked it up.

Add the following to the Keycard’s onInteract Event Property:

Entity: Keycard1

Script: HideShowScript

Event: Hide()

Edit the Properties for keyCard1.
Select keyCard1 as the Entity.
Select the Hide event.

Preview your game and interact with your keyCard. You will find that it disappears, simulating that you have “Picked it up”. 

Return to Edit mode.

To make the outer door unlock, you will need to add a Script to it. The Script is the same Script used on the bank vault door.

Open the Entity Editor for the outer door.

Open the Entity Editor for the outer door.

At the bottom of the Entity Editor click the Add to Entity button. Select Script > LockedDoor and press A to add the LockedDoor Script to this door.

Add the LockedDoor Script to the outer door.

Check the locked checkbox to ensure that the door starts locked.

Lock the outer door using the locked checkbox.

Click the + on the onInteract and choose the Door instance > LockedDoor > ToggleOpen(). This will mean when you interact with the door it will open, but only if it’s unlocked.

Add the OpenDoor() Event Listener to the onInteract Event Property of the front door.

Unlocking the door is the last piece of this puzzle.

Open the Entity Editor for the Keycard once again.

Return to the onInteract field. This time we will also add the unlock function to the onInteract event. Select the following:

  • Entity: outer door (make sure to select the right door here)
  • Script: LockedDoor
  • Event: UnlockDoor()

Note: Make sure that you have both the key1 / HideShowScript and bankVaultDoor1 / LockedDoor in the onInteract field.

Select the UnlockDoor as the additional Event Handler to the onInteract Event Property of the Key.
Select your door as the entity, then the LockedDoor script, and the UnlockDoor event.

Close the Entity Editor for the Keycard. You have created a way to pick up the key and unlock the door. 

Preview your game. Interact with the Keycard and you should find it disappears (and behind the scenes we know the door has unlocked). Then, interact with the outer door and the door should swing open. 

Tech Tip: Testing

Testing is a vital part of making games as it ensures that the game you have made is doing what you expect it to do. 
Most of the time, developers test the game as they develop new features, but sometimes adding a new feature, or changing a part of the gameplay, may cause unexpected or unwanted things to happen to other parts of the game. Unwanted behaviour in a game is called a “bug” and needs to be fixed before continuing with the game development.
For example, in our situation, selecting the wrong door to “open” when the player interacts with the keycardReader might cause the vault door to open, rather than the exit. This would be very confusing to the player, and they won’t be able to get out!
Test your game regularly to make sure your game is doing what you want it to do, and make sure to fix any problems when they come up.

Recap

Congratulations, you have created a bank heist game. In this tutorial you have looked at:

  • What are Events and how do we use them
  • Using the Event Properties to add interactivity to the game
  • Changing a mesh and adding more interactivity to craft new puzzles

How did you get on? If there were moments which didn’t work how you wanted, now is a good time to revisit your game and fine-tune it, and practice what you have discovered in this tutorial.

Adding Polish

If you want to carry on adding to this game, here are some ideas that you can explore using the techniques we have looked at in this tutorial:

  • Hide the keycard in the bank vault itself, so that the player has to get in the bank vault before they can leave
  • Give your player the choice to either blow up the vault door, or use a keycard hidden somewhere else in your game
  • Create another obstacle, where the player has to pick up some TNT before it appears outside the bank vault door.
  • Make a dungeon “escape room” by linking multiple obstacles that need to be solved before the player can escape

Next Up: UI

The next tutorial will look at how we can display information to your players using the inbuilt UI system. This will allow you to add written narrative elements and dialog, show player health or points, and show the player a win or lose message. 

Combining communication with events will enable you to create completely unique and exciting narratives that reward and challenge your players.

Basic Tutorials 3: UI

Categories
Basic Tutorials

Basic Tutorial 1: Packages

Preface

This tutorial assumes that you understand the basics of entering Crayta’s CREATE mode and have some experience building levels.

In this tutorial, you will look at how you can use the Packages within Crayta to add playful Entities to our game.

Create Your Game

Navigate to CREATE mode in the Crayta menu and under CREATE A NEW GAME press A on EMPTY GAME.

Select STARTER: EMPTY GAME.

Name your new game “Robot Run Race” and press APPLY AND CONTINUE. Choose an image and press CREATE AND ENTER.

You should now see your empty Game. If any of that was confusing, head back to the Basic Workflow Tutorial which guides you through the process of creating and editing your own Game from the very beginning. 

Otherwise if you are still with me, great! Read on!

Adding Packages

Components are the basic building blocks of our game, and they include Sounds, Meshes, Scripts, Templates and Voxels. You can access the Components through your Library

Open the Library by pressing Y

If this is your first time using the Library, and you want a better overview, head back to the Basic Workflow Tutorial.

The Blank Game template has a range of basic Components that you can use to make your game idea a reality. However, there are many more available that have been created by Crayta makers and the Crayta Community. You can add these Components by visiting the Community tab and installing groups of Components which are called Packages.

When you install a new Package the Components are automatically added under the appropriate Library tab.

This tutorial will guide you through installing the Robot Run Race Package, which includes everything you need for the game you are about to make. 

When you open the Library, your controller is now moving the highlight square in the Library menu.

Press Y to change tab to the Community tab.

Navigate the Community Packages and find the Robot Run Race Package.

With the Package highlighted, press A to install.

When installation is complete, the items from the Package will be added to the corresponding tab in the Library.

Adding Templates To Our Game

To return to the Library press Y.

Press R2 to change tab to the Templates tab. Here you should see three new Templates that were added by installing the Robot Run Race package. 

In addition to the standard Player and User templates, we now also have RobotRunRace_Competitor, RobotRunRace_FinishLine and RobotRunRace_Racetrack. These templates feature custom functionality, and we can use them in lots of different ways.

To add RobotRunRace_Racetrack (the 3rd template in the list) to our Hotbar, highlight the Template by using the D-Pad in the Library window, and press A. The Library will disappear, and you will find that you now have a racetrack in your Hotbar.

You can move around to find a good spot, and rotate your racetrack by changing the direction you are facing with the Right Analog Stick. When you are happy with its position press R2 to place it. Remember, if you change your mind you can undo by pressing LEFT D-PAD.

Press RB to change to an empty Hotbar slot. This makes it easier to navigate and edit your world.

How exciting! You have a basic racetrack, with a start line. But you are the only competitor? It’s called Robot Run Race for a reason, right? Let’s get some robots involved. 

Adding A Robot

Open your Library and select RobotRunRace_Competitor from the Templates. Press A to equip it.

Preview the game by pressing and holding D-PAD DOWN.

Tech Tip: Preview Often

There are two modes in the Crayta CREATE mode. Edit mode and Preview mode. To change between them, press DOWN on the D-PAD.

Edit mode: Here is where we can build our game world, add entities and change their properties. When you do anything in this mode it is saved. In this state, your game is not running, so entity behaviours such as movement won’t occur until we Preview or Run our game.

Preview mode: This is your game in action. Enter this mode to start any entity behaviours and test your game. When you do anything in this mode it is not saved. 

Regularly Editing and Previewing your game follows the same process that game developers use when they are building a game. Always remember to Preview your game, to see how the changes you make in the Edit mode impact your gameplay.

Oh no! Come back Robot! You’re going in the wrong direction! You’re not supposed to wander off.

When you’ve spent enough time chasing the Robot hold D-PAD DOWN to return to the Editor.

Don’t panic, we can rectify the direction the Robot is running in easily, but first let’s take a look at how we can customise this part of the racing game.

Changing The Mesh

Press RB to select an empty hotbar slot.

Look at your Robot with your crosshair and an outline should highlight it with yellow.

With the Robot Competitor highlighted, press X to open the Entity Editor. You can open the Entity Editor for any Entity in your game.

Using the Entity Editor, we can change some of the properties of our Robot. To start with, we are going to make it a Wardrobe.

Use the D-PAD to navigate the Entity Editor menu. Highlight the meshAsset dropdown box and press A.

Scroll the list using the Left Analog stick. It’s in alphabetical order, so scroll down until you can see Wardrobe on the list. Then, use the D-PAD UP/DOWN to highlight Wardrobe. Press A to select.

Notice how the Robot has now magically transformed into a Wardrobe. This is because we have told Crayta that we want to use the Wardrobe Mesh with this Entity, instead of the Robot Mesh

Creative Control

You can select any mesh from the meshAsset dropdown, and this can be a great way to experiment with different game themes. Maybe it’s bedroom furniture that’s racing, or different vehicles, it’s your choice.

And just for fun, close the Entity Editor by pressing B. Preview the game by pressing and holding D-PAD DOWN. Congratulations on making a “chase the wardrobe” game.

Return to the game, and return the Competitor to being a Robot instead of a Wardrobe (if you like).

Tech Tip: Entities, Properties And Behaviours

In this example our Entity Template is RobotRunRace_Competitor, but the actual Entity in the game is named robotRunRace_Competitor1. It is just one instance of RobotRunRace_Competitor. We can add as many instances of RobotRunRace_Competitor as we like.

Entities in Crayta have Properties

Properties are information stored about the entity, such as its name, position and rotation. When we selected a new meshAsset for this entity we changed one of its properties.

Changing Direction

If your robot was anything like mine, it ran in the completely wrong direction from the racetrack. Furthermore, it seems to be facing completely the wrong way. We can use the same technique we used to change the mesh to change the other properties of our entity in the Entity Editor and fix these mistakes too!

If your Robot is facing away from the racetrack then you need to follow these steps to make it face the correct direction.

Again, look at the Robot and press X to open the Entity Editor.

Use the D-PAD to navigate the Entity Editor. Highlight the middle box next to the label marked “rotation” and press A to begin editing this value.

You can use D-PAD RIGHT or LEFT to increase or decrease this number. When you change its value, you should find that the Robot starts to rotate.

Rotate the Robot to make sure it is facing in the direction it of the racetrack. It’s likely to be either 0, 90, 180 or 270.

Press B to stop editing the number and press B to close the Entity Editor.

Hold D-PAD DOWN once more to Preview your level.

Oh! It’s better, but it’s still not quite right. Finally, we need to make the Robot move in the direction its facing. To do this, we need to return to the Editor and open the Entity Editor one last time.

With the Entity Editor open, navigate to the boxes next to “speed”.

Tech Tip: Three Dimensions

3D games use three different numbers to determine a position in the world. A 3D coordinate system has values for LEFT and RIGHT (X), AWAY and TOWARDS (Y), UP and DOWN (Z). 

Our “speed” values show how much our object will move in each of these directions each time the screen is updated (about 60 times per second, or 60 FPS).

By default, our CompetitorScript moves 100.0 units every frame on the X axis. Changing this value to -100.0 would move our entity in the opposite direction. Positive values move one way, negative numbers move the other.

Look at which way your Robot moves when you Preview the game. To move in the direction of our racetrack, we will need to have either 100 or -100 in one of the first two boxes, with the final box always 0. If it is already moving in the correct direction, note down what the current values are, and experiment with the following.

Try the following combinations of numbers. Consider what is happening each time, and choose the right one for your Robot. Remember, if something breaks or does not look right you can undo the last action with LEFT D-PAD.


XYZNotes
speed100.00.00.0Robot moves RIGHT
speed0.00.00.0Robot STOPS
speed-100.00.00.0
speed0.0100.00.0
speed0.0-100.00.0
speed0.00.0100.0

To speed this up, you can also work it out logically. 

If your Robot is moving LEFT/RIGHT compared to your racetrack then X will need to be 0.0, and Y will need to be either +100.0 or -100.0. 

If your Robot is moving directly opposite away from your track then Y will need to be made negative (or positive if it was negative already).

Preview your game and make sure your Robot is travelling down the racetrack.

Success! Your Robot is now racing to the finish line.

Adding More Competitors

Now is a good opportunity to practice what you have done so far. Add more competitors to your game. You will need to adjust their mesh, rotation and speed properties to be the same as the first one. Repeat the steps from Adding A Robot if you want to follow the instructions again to remind yourself how to add competitors to the game. 

Preview your level and make sure that you have some Robots, that all travel in the same direction in a race.

To make things more interesting we can change the speed of some of our Robots.

Open the Entity Editor and navigate to the CompetitorScript’s “speed” boxes.

Change your 100.000 to 300.000, or if it is -100.000 change it to -300.000 and you will see that the speed of the Robot increases.

Change this value for all of your robots and Preview your game. Notice that even though they are made with the same template, they can be made to move in different directions and different speeds (or behave slightly differently). This isn’t limited to the movement, as you will discover in the next tutorial.

Finishing Touches

The last thing we need to do is determine who won our race.

Open the Library and add the RobotRunRace_FinishLine to your Hotbar menu.

The FinishLine template includes a finish line, two flags and a Trigger Volume – an invisible box stretched between the two flags. The Trigger Volume has some special features.

One of your robots will enter this Trigger Volume, and a Script attached to it will tell you the name of the winning Entity. Make sure that the glowing blue trigger volume is the opposite side of the finish line to the robots, such as in this handy reference image.

Preview your game one more time.

Race your robots! Get to the start line, and race against them. First entity to the finish wins and…well…you’ll see what happens!

Recap

This tutorial was about taking you to the next level by adding packages and adjusting the properties of entities in your game. In this tutorial you have covered:

  • Packages in Crayta’s CREATE mode
  • Adding Templates to the game
  • Changing an Entity’s mesh from a wardrobe to a robot
  • Changing other Entity Properties including rotation and speed

Adding Polish

You have the beginnings of a game, but Robot Run Race could go in whatever direction you choose (just like the wardrobe). You can use the same techniques to setup a race with your friends, racing against each other, or some ultrafast teapots? Some other things you could add might include:

  • Adding a high-up area to spectate
  • Adding more lanes, more competitors and space for players to race too
  • Remove the racetrack and make an obstacle course for players to race through. The winner is the first one to the finish line!

You could also look at installing some other packages that would make for some compelling races. For example, try downloading the DancingCacti package, and use each of the Dancing Cacti to decorate your scene, or as obstacles for your racers!

Next Up: Action!

The next tutorial adds a lot more interactivity, and looks into templates that enable you to trigger events, make things explode and create puzzles for your players to solve.

Basic Tutorial 2: Events