Categories
Advanced Tutorials

Using Fonts in Crayta

As you develop your game, you might find that you want to alter the fonts used within the UI to complement the style or theme of your game.

This can be done by referencing supported fonts (see below for the list) in the css portion of your UI widget:

@font-face {
   font-family: FONTNAME;
   src: url('https://content.crayta.com/fonts/FONTFILE');
   font-weight: 400; /* 400 = Regular, 500 = Medium, 600 = Semi-bold, 700 = bold */
}

h1 {
   font-family: FONTNAME;
}

The supported fonts are:

FONTNAMEFONTFILE
This image has an empty alt attribute; its file name is 55cda967-asset.pngAsset-Regular.ttf
This image has an empty alt attribute; its file name is ddfe4ce5-bangers.pngBangers-Regular.ttf, Bangers.ttf
This image has an empty alt attribute; its file name is 83ac5b92-barlow.pngBarlow-Black.ttf, Barlow-BlackItalic.ttf, Barlow-Medium.ttf, BarlowCondensed-Regular.ttf
This image has an empty alt attribute; its file name is 64f6434d-bevan.pngBevan-Regular.ttf
This image has an empty alt attribute; its file name is 65b178cc-frijole.pngFrijole-Regular.ttf
This image has an empty alt attribute; its file name is 52a8c68a-jolly-lodger.pngJollyLodger-Regular.ttf
This image has an empty alt attribute; its file name is ab3136b1-lilita-one.pngLilitaOne-Regular.ttf
This image has an empty alt attribute; its file name is ed56a699-luckiest-guy.pngLuckiestGuy-Regular.ttf
This image has an empty alt attribute; its file name is 01166fa2-maiden-orange.pngMaidenOrange-Regular.ttf
This image has an empty alt attribute; its file name is 61f0d21d-montserrat.pngMontserrat-Bold.ttf, Montserrat-BoldItalic.ttf, Montserrat-Light.ttf, Montserrat-LightItalic.ttf, Montserrat-Regular.ttf
This image has an empty alt attribute; its file name is ba8416ad-noto-san.pngNotoSans-Regular.ttf
This image has an empty alt attribute; its file name is c0ad4f8b-orbitron.pngOrbitron-Black.ttf, Orbitron-Bold.ttf, Orbitron-Medium.ttf, Orbitron-Regular.ttf
This image has an empty alt attribute; its file name is 3da27160-oxygen.pngOxygen-Regular.ttf
This image has an empty alt attribute; its file name is 73f6d6f1-pt-sans.pngPTSans-Regular.ttf
This image has an empty alt attribute; its file name is 58f335fb-roboto-mono.pngRobotoMono-Regular.ttf
This image has an empty alt attribute; its file name is b119ef14-rye.pngRye-Regular.ttf
This image has an empty alt attribute; its file name is 7ca4963e-sancreek.pngSancreek-Regular.ttf
This image has an empty alt attribute; its file name is e727ac72-space-mono.pngSpaceMono-Regular.ttf

Categories
Advanced Tutorials

Player Animation: Grips, Actions and Events

Crayta lets you assign a ‘grip’ to a player.  A grip defines the set of movement animations that this player will start using.  For example, setting a player’s grip to Shotgun will see the player run, jump, crouch, etc, as if they were holding a shotgun with both hands.  Switching this to Melee will switch these animation to a one-handed hold of a sword-like weapon.  It is up to your game to attach shotguns/swords/whatever to your player’s hands in conjunction with setting the grip type.

Depending on the grip that has been assigned various actions can be played.  For example, if the player is using the Shotgun grip, they can do a Fire or Reload action.  However, when using the Melee grip, there is no such thing as a reload (you can’t reload a sword!), so that doesn’t have a Reload action.

To trigger an action, for example a reload, just call self:GetEntity():PlayAction(“Reload”)PlayAction takes an optional second parameter, which is a table of optional parameters for this animation. 

NameTypeDescription
playbackSpeednumberSets the speed to play this animation at. 2 = double speed, 0.5 = half speed.

Note: If playbackTime is also set, you’ll get a warning, and playbackTime will be preferred)
playbackTimenumberSets the time that this animation should take. 1 = 1 second, 10 = 10 seconds.

Note: If playbackSpeed is also set, you’ll get a warning, and playbackTime will be preferred)
eventsTable of lua functionsSome actions trigger events – these are functions that will be triggered in your Lua code once the animation for an action reaches a certain point.

An event can be either a standard event, or a branching event. A standard event expects your lua function to return nothing.

A branching event expects your lua function to return a bool. Events can be omitted from this table, if a branching event is omitted, the default return value for this branching event will be used. See examples of events below.

Grips, actions, and events

Grip Name: Carry

Actions

None

Grip Name: Cleaver

Actions

  • Melee – This will perform a ‘chopping’ animation
    • Standard Events:
      • ChopImpact – This will trigger at the point in the animation when the cleaver looks like it has hit the chopping surface
    • Branching Events::
      • IsChopComplete – If false, another chop will take place immediately without playing the intro of the animation again.  If true, the chop animation will play its outro sequence and complete

Grip Name: Cuff

Actions

None

Grip Name: Unarmed

Actions

None

Grip Name: Knife

Actions

  • Melee – This will perform a ‘slashing’ animation
    • Standard Events:
      • MeleeImpact – This will trigger at the point in the animation when the knife looks like it should hit its target

Grip Name: Pistol

Actions

  • Fire – This will perform a ‘shooting’ animation
  • Reload – This will perform a ‘reload’ animation
    • Standard Events:
      • AmmoAdded – This will trigger at the point in the animation when the pistol clip has been inserted into the pistol
  • Melee – This will perform a ‘pistol whip’ animation
    • Standard Events:
      • MeleeImpact – This will trigger at the point in the animation when the pistol looks like it should hit its target

Rifle

Actions

  • Fire -This will perform a ‘shooting’ animation
  • Reload – This will perform a ‘reload’ animation
    • Standard Events:
      • AmmoAdded – This will trigger at the point in the animation when the clip has been inserted into the pistol

RPG

Actions

  • Fire – This will perform a ‘rocket launch’ animation
  • Reload – This will perform a ‘reload’ animation
    • Standard Events:
      • AmmoAdded – This will trigger at the point in the animation when the rocket has been inserted into the RPG

Example

Here’s an example of a reload action for a shotgun grip being performed at double speed, with the IsReloadComplete and AmmoAdded action events implemented.  The reload animation will keep on playing until the number of self.bullets reaches self.properties.maxBullets

local animData = {}
animData.playbackSpeed = 2.0
animData.events =
    {
        IsReloadComplete = function ()
           Print("Checking if full")
           return self.bullets == self.properties.maxBullets
        end,
        AmmoAdded = function ()
            self.bullets = self.bullets + 1
            Print("Added Bullets, current ammo = " .. self.bullets )
        end
    }
    self:GetEntity():PlayAction("Reload", animData)

Global Events

OnCompleted – This applies to all actions and will trigger once the animation for the action is no longer playing

Categories
Advanced Tutorials

Basic Coding #6: Make A Highly Dangerous Soccer Game

Preface

Crayta allows you to create any game you can imagine. Sometimes thinking of a game completely from scratch can be a bit daunting, but what about taking a game that already exists and turning it on its head? Enter, highly dangerous soccer – a soccer game which involves guns, traps and the odd exploding barrel.

Introduction

This tutorial will guide you through taking a Team Deathmatch level template and turning it into a soccer game using some Lua scripting in Crayta’s Advanced Editor

This tutorial is aimed at Crayta players who are comfortable with most of the tools in the Advanced Editor, but assumes no prior coding experience. If this is the first time you have opened the Advanced Editor then you may want to go through the Advanced Workflow Tutorial and the Learn To Code With Crayta tutorials to familiarise yourself with the interface. 

In this tutorial you will explore:

  • Changing the Team Deathmatch scoring and game mechanic using Lua Scripting
  • How to “kick” a football
  • Adding custom danger and explosives to your football pitch

The Beautiful Game

This isn’t going to be a typical football game. This is going to be a Crayta style soccer game. Firstly, let’s simplify the rules to give us a game where:

  1. Two teams of players kick a ball around a pitch
  2. The object of the game is to put the ball in the opposing team’s goal

Solving these problems is fairly straightforward.

Players can already kick a ball around the world (using the inbuilt physics engine) so you don’t need to code this yourself.

The Team Deathmatch game mode already has team management and scoring functionality to manage the team assignment and some of the scoring so you don’t need to code this yourself either!

This leaves the goal scoring mechanic and any level based aspects to code. Time to dive in.

Creating The Game

Start by creating a new Team Deathmatch game. Add a Ball (Football Jumbo) Prop to the game.

Use the Entity Editor to change its name to “football” and check the physicsEnabled checkbox.

Close the Entity Editor. Build a goal on your map using Voxel tools. This goal is going to be tweaked and updated when you come to test and balance your game, so don’t spend too long here. 

Ball Respawn

When the ball is kicked into the goal it needs to allow a short time for player celebrations and then respawn at the center point.

Add a Trigger to the World. Move the Trigger to the goal and increase its size until it fills the whole goal. Name the Trigger goalTeam1.

You will use the Trigger to call a function in the gameScript when the ball enters the goal. 

Add a Locator to the center of the game. You will use this Locator as the spawn point for the ball. Name the Locator footballSpawnPoint.

Click on the gameController in the Entity Explorer and open the Code Editor for the gameScript.

This Script contains a lot of the logic for the game, including the scoring when a Player kills another Player (as this is the game logic for a Team Deathmatch game) and assigning Players to teams. You can look through the code to see how the game works. In this guide you will be repurposing this logic to work the way you want it to. 

The gameScript needs a reference to the footballSpawnPoint so that it can respawn the ball at this location. Add a new Property to the Property Bag with the name “footballSpawn” of type “entity”.

{ name = “footballSpawn”, type = “entity” }

Use the Entity Explorer / Editor on the right hand side to drag the footballSpawnPoint to the footballSpawn Property on to the gameController / gameScript Property Bag.

To handle the logic when the ball enters the goal we will now write a function which is called by the Trigger from the OnTriggerEnter Event

Add a function after the Property Bag called GoalScored.

function GameScript:GoalScored(other, theTrigger)

end

The function contains two arguments:

  1. other – this is a reference to the Entity which has entered the Trigger.
  2. theTrigger – this is a reference to the Trigger itself. We will use the same function for both goals, so we will need to use this reference to figure out which team has scored.

To respawn the ball the following steps should occur:

Fill out the function so it contains the following:

function GameScript:GoalScored(other, theTrigger)
	
	-- Check if the thing which entered the goal Trigger (other) was called football
	if other:GetName() == “football” then

		-- Set ball position to ballSpawn position
		other:SetPosition(self.properties.footballSpawn:GetPosition())

		-- Halt ball velocity and spin
		other:SetVelocity(Vector.Zero)
		other:SetAngularVelocity(Rotation.Zero)
	end
end 

Use the Entity Explorer to call the GameScript:GoalScored function from the goalTeam1 Trigger OnTriggerEnter Event. 

Select the goalTeam1 Trigger in the Entity Explorer. Scroll to the onTriggerEnter dropdown box. Select the following:

  • Entity: gameController
  • Script: gameScript
  • Event: GoalScored

Test the game and check that when you score a goal with the ball, the ball is respawned at the footballSpawnPoint Locator position.

Adding Time For Celebrations

It’s not scoring a goal unless there is a little bit of time set aside for gloating. You can add a delay before the ball is respawned to the spawnBallLocator by using the inbuilt scheduler.

Tech Tip: Wait Off The Main Thread

The Wait() function in Crayta will stop the next line of code from running until after a certain amount of time, which can be very useful. However, this could be dangerous because it could cause the whole game to freeze whilst it waits for Wait() to complete. To avoid this, the Crayta developers have made sure this can’t happen – if you try to use Wait() on its own it just won’t do anything.

-- some code here
Wait(5.0) -- this Wait() will be ignored
-- some more code here

To use Wait() you will need to use self:Schedule(). This function moves the code within the brackets away from the main thread, so the game won’t lock up. This means you can now use the Wait() function. For example:

self:Schedule(
function()
	Wait(5.0) -- wait for 5 seconds before moving to the next line
	-- Here is some code that is executed after the wait function
end
)

Change your GoalScored function to reflect the following:

function GameScript:GoalScored(other, theTrigger)
	
	-- Check if the thing which entered the goal Trigger (other) was called football
	if other:GetName() == “football” then
		
		-- Use the scheduler
		self:Schedule(
			function()
				-- wait for 3 seconds
				Wait(3.0)

		-- Set ball position to ballSpawn position
		other:SetPosition(self.properties.footballSpawn:GetPosition())

		-- Halt ball velocity and spin
		other:SetVelocity(Vector.Zero)
		other:SetAngularVelocity(Rotation.Zero)

	end -- end the code called within the scheduler
)

	end -- end ball name check

end -- end GoalScored function

Test your changes to make sure the code still works, and that you have time to celebrate (feel free to tweak the length of the Wait()).

Adding The Score

The Team Deathmatch game template has some scoring logic already implemented. To score a point in Team Deathmatch you just need to kill another player. However, for the football game you want to score a point when the ball enters the goal, and not when a Player is killed. To do this you combine the goal scoring functionality you’ve already written with the scoring mechanic that is prebuilt.

If you scroll to the bottom of the gameScript you will see two functions:

  • AddTeamScore(team, num) – this function adds an amount to the team score. In the brackets; 
    • “team” refers to the team number (1 or 2) to add score to, and 
    • “num” refers to the number of points to add to their score (defaults to 1)
  • OnUserDied(userEntity, fromEntity, selfMsg, otherMsg, youKilledMsg) – this function is called when one Player kills another, and calls AddTeamScore. You will remove the call to AddTeamScore.

Within the OnUserDied() function, add a comment (–) to the start of the following lines:

fromUser:SendToScripts(“AddScore”, self.properties.killScore)

self:AddTeamScore(fromUser:FindScriptProperty(“team”), self.properties.teamKillScore)

So that the line appears as a comment. This is a technique called “commenting out” and is useful for developers to turn on or off a line of code without losing the code completely by deleting it. Your function should now read:

function GameScript:OnUserDied(userEntity, fromEntity, selfMsg, otherMsg, youKilledMsg)
	
	-- send game event to anyone who wanted
	self.properties.onUserDied:Send(userEntity, fromEntity, selfMsg, otherMsg, youKilledMsg)

	-- find user for player who killed us (if there is one)
	local fromUser = (fromEntity and fromEntity:IsA(Character)) and fromEntity:GetUser() or nil
	-- add score
	If fromUser then
-- fromUser:SendToScripts(“AddScore”, self.properties.killScore)
If self.properties.hasTeams and self.properties.teamKillScore > 0 then
	-- self:AddTeamScore(fromUser:FindScriptProperty(“team”), self.properties.teamKillScore)
end
end
	
end

You have removed the logic which adds scores to the team scoreboard and the individual player score, which means you can now write your own.

To add the scoring mechanic to the GoalScored function, you will borrow one of the lines of code you just commented out. 

Copy the following line of code (Ctrl+C) from the OnUserDied function:

self:AddTeamScore(fromUser:FindScriptProperty(“team”), self.properties.teamKillScore)

Return to your GoalScored function within gameScript and paste this before the Wait() function. Change the variable fromUser to theTrigger. 

self:AddTeamScore(theTrigger:FindScriptProperty(“team”), self.properties.teamKillScore)

Your GoalScored function should now read:

function GameScript:GoalScored(other, theTrigger)
	
	-- Check if the thing which entered the goal Trigger (other) was called football
	if other:GetName() == “football” then
		
		-- Use the scheduler
		self:Schedule(
			function()

				-- Apply the team score
				self:AddTeamScore(theTrigger:FindScriptProperty(“team”), self.properties.teamKillScore)

				-- wait for 3 seconds
				Wait(3.0)

		-- Set ball position to ballSpawn position
		other:SetPosition(self.properties.footballSpawn:GetPosition())

		-- Halt ball velocity and spin
		other:SetVelocity(Vector.Zero)
		other:SetAngularVelocity(Rotation.Zero)

	end -- end the code called within the scheduler
)

	end -- end ball name check

end -- end GoalScored function

The “theTrigger:FindScriptProperty(“team”)” part of the code is looking for a Property called “team” from any Script attached to the goalTeam1 Trigger. At the moment this Entity does not have any such Property

To add this, add a new Script to the goalTeam1 Trigger and name the Script goalTeamScript. The Script will be very simple and only include this Property. The whole code should read:

local GoalTeamScript = {}

GoalTeamScript.Properties = {
	{ name = “team”, type = “number”, default = 0 }
}

return GoalTeamScript

Set the Property to 1 in the Entity Editor.

Make sure you have saved the gameScript and the GoalTeamScript and test your game. After the game starts (there is a lobby countdown first) you should find that when you score your team gets a point. And the crowd goes wild!

Kicking The Ball

Dribbling in the game is possible with a bit of careful control, and this makes for quite a nice requirement of skill. Passing and shooting on the other hand are not currently possible. Let’s remedy this. 

To “kick” the ball you will need to check some conditions, and then apply some force to the ball in the direction the Player is facing. The way you will kick the ball is similar to how Russ builds a Blast Hammer in one  of the Crayta Livestreams: https://youtu.be/9286X65O-xo

First, open the Player in the Entity Editor using the dropdown (currently set to World).

Add a Trigger to the Player. Make its size 200 x 200 x 200 and move it just in front of the existing Trigger on the X axis (red arrow). Name the Trigger kickTrigger.

You will use this kickTrigger to determine if the football is close to the Player.

Create a Script Folder in the Player called KickLogic. Add a Script called KickLogicScript and open it in the Code Editor.

The main difference between Russ’ Blast Hammer Script is instead of launching a player it will apply an impulse force to the football. Start by adding some of the Properties that you will need:

KickLogicScript.Properties = {
	{ name = “strength”, type = “number”, default = 250 },
{ name = “kickTrigger”, type = “entity” },
{ name = “launchVecotr”, type = “vector” },
}

Saving the Script should make these Properties appear in the Entity Editor for the KickLogic Script Folder.

You will use the OnButtonPressed function, which will be automatically called when the User presses a button, to call a kick function which performs all the logic necessary to kick the ball.

Add the following code to the Script:

-- Called when the player presses a button
function KickLogicScript:OnButtonPressed(buttonName)
	-- Check this is the secondary button
	if buttonName == “secondary” then
		-- Call the Kick function
		self:Kick()
	end
end

-- Called from the OnButtonPressed function
function KickLogicScript:Kick()
	
-- Get a reference to the football
local ball = GetWorld():Find(“football”)

-- Check the ball exists
if ball then
	-- Check the ball is within the players kickTrigger
	If self.properties.kickTrigger:IsOverlapping(ball) then
		
		-- Store the balls position in local variable
		local ballPosition = ball:GetPosition()

		-- Work out the vector from the ball to the player
		local relativeVector = self:GetEntity():GetLookAtPos() - ballPosition

		-- “Normalize” this vector, so that it is simply directional and doesn’t
			-- refer to the distance (we don’t need the distance)
			local normalizedRelative = relativeVector:Normalize()

			-- Combine the direction any height trajectory we set in the launchVector
			local combinedVector = normalizedRelative + self.properties.launchVector

			-- Multiply by the strength of the kick
			local kickVector = combinedVector * self.properties.strength

			-- Apply this vector to the ball as an impulse
			ball:AddImpulse(kickVector)
		end
	end

end

Now set your Properties for this Script to the following:

  • strength: 60000
  • kickTrigger: kickTrigger (drag and drop the kickTrigger from the Player to set this)
  • launchVector: 0, 0, 1.2

Before we test this, we also need to remove the current functionality for the “secondary” button, which currently toggles iron sight mode on the gun you are holding.

Open the Gun Template using the Entity Explorer dropdown.

Use the Entity Editor to remove the ironSightItemScript from the Gun Template.

This will stop the “secondary” button from using the iron sight.

Now test your game and try kicking the ball. You can tweak the values in the Properties of the Script to suit how you want the game to “feel”.

Respawn Players When You Score

Scoring returns the ball to its start location, but what about the Players? To return the Players to their initial spawn point you can leverage the existing game mechanics. 

Add the following line of code within the gameScript:GoalScored function after you reset the physics on the football:

-- reset physics on the football
other:SetVelocity(Vector.Zero)
other: SetAngularVelocity(Rotation.Zero)

-- return players to original spawn points
GetWorld():ForEachUser(
	function(userEntity)
		userEntity:FindScript(“spawnUserScript”):SpawnInternal(false)
	end
end

Test your game and check that when the ball is respawned after scoring, so are the Players.

Building A Stadium

Now that you’ve coded the basic game mechanic it’s time to make this game a bit more interesting. Use the Voxel tools to build a stadium for your football game. Make sure to build a wall around the stadium to keep the ball in play and keep the tension mounting.

Think about theming the stadium. This game could be happening at any time, in any place. The fact that you are carrying a machine gun (which can still kill the opposing team) creates a somewhat…murderous…environment, so have fun with the setting.

To build another goal for the other team, extract your original goal across the pitch to make sure they are exactly opposite and exactly the same size. You can then remove a strip of blocks and extract it back to its original setting.

Copy the Trigger goalTeam1 Trigger. When you paste the duplicate you should find that it automatically changes the name to goalTeam2. Move it into the other goal, and remember to use the Entity Editor to change the Trigger’s GoalTeamScript to team 2.

…And that’s it! Remember to test your game, and try out both teams by inviting some friends along for a (deadly) kickabout.

Recap

Congratulations! In this tutorial you made a fun soccer game, made somewhat more sinister by the inclusion of automatic rifles.

You’ve developed skills in:

  • Respawning a ball and players to their original location
  • Modifying a game template to change the score mechanic of a team based game
  • Using triggers to score points

Adding Polish

Whilst this is the conclusion of the tutorial, there’s no reason to stop here. In fact this could be just the beginning. Flex your creative muscles by using what you’ve learned here, and in the other coding tutorials to:

  • Add a Script to the ball to store the last player to touch the ball and then Add Player Score to them when they score a goal
  • Add some spinning sawblades (like in Basic Tutorial 3: Events) or some laser meshes (such as in Basic Tutorial 5: Combat) to create even more danger in your game
  • Add player score when they hurt or kill another player to encourage more dangerous play
  • Add some exploding barrels (like in Coding Tutorial 1: Exploding Barrels) that explode when hit by the ball. You can use what you learned in the “Kicking The Ball” chapter to fire the ball across the field
Categories
Advanced Tutorials

Advanced Level Design 4: Particles and optimisation

Preface

You have reached the final tutorial in this series of Level Design Tutorials. Adding finesse and quality to a game level is usually the most time consuming part, and has the least amount of noticeable difference. However, all of the small details that you add in the final 20% of level design add up to a much greater player experience, so it’s worth investing a little bit more time and energy, to really make the level worth playing.

Introduction

In this tutorial, you will look at further developing the narrative of the level by creating a dramatic backdrop in the form of castles. These backdrops could be anything linked to the theme of your game. They are also a great opportunity to tie together the narrative in many games, if you have made a series of games that are linked in some way.

In addition to the backdrop, you will also look into some of the Effects that are available within Crayta, so that you can add movement and natural effects like fire to your game. This tutorial also touches on optimisation, which is essential to ensure that your game demands are within the bounds of what is possible on Crayta and Google Stadia, as well as looking into final touches in the Game Settings panel to allow your UI to also be a part of your story.

Open Your Game

Start by reopening the level you are working for for this series of tutorials. If you haven’t got one, it would be worth learning some of the Advanced Editor tools and techniques before starting this tutorial, so run through that tutorial, and then start this series of tutorials with Level Design Tutorial #1.

Your level is looking polished, but it’s not quite finished.

Creating A Kingdom

Large, faraway phenomena can add depth and feeling to the game, as well as help your players to orient themselves in the level, especially if this is their first time playing your game. It gives your game a sense of place, and describes the type of world that exists outside of the walls of your level. Structures and landscapes in the distance help to further embed the narrative and theme of your game, whilst simultaneously expanding the size of the world in the mind of the player.

Revisit your reference document, or search online for images relating to your theme. You are looking for inspiration to create dramatic backdrops that embellish the story of your game. For this example, medieval villages seem to have a range of different phenomena in their backdrops including castles, churches, mountains, guard towers, windmills, and other villages on hilltops. Once you have a list of several ideas, you can choose one or two that you would like in your game. For this tutorial, you will look at creating a castle that overshadows this village at the edge of its kingdom.

Creating A Castle Silhouette

To start, you will create a silhouette of the structure which will be visible in the distance in your game. The shape needs to be recognisable, but doesn’t necessarily need the same level of detail as the buildings and landscape in your game world because your players will not be able to see it up-close. In game design, this is called LODing (level of detail) and is a technique used to optimise the gameplay, whilst maintaining the aesthetic effect of the level. 

To start, move your view away from your village to a blank area of your level.

Choose the Voxel Meshes tab in the Library. You should see your Voxel Mesh creations as well as the Terrain which is the basic landscape of your level.

Click Create New Asset. Call it Castle and select it from the Voxel Meshes menu.

Place it in your game world, and move your camera so that you can see the initial Voxel clearly.

Just like building the house, you can build on top of this Voxel and Crayta will ensure that the Voxels all form the same Voxel Mesh. Click the Shape tool and add Voxels to your Castle Voxel Mesh in the shape of a cuboid. Expand the shape so that it creates a silhouette 1 Voxel thick.

Before applying the Voxels, move your camera to your game level. Check to make sure that your castle will be visible from your game world, as well as being an appropriate size and distance to be believable.

Once you are happy with the placement and size of your castle, return the view to look closely at the Voxel Mesh and use your reference image as a guide to add a general shape.

It doesn’t need to be perfect at the moment, but having a general shape will help you to make sure it is visible, and recognisable at a distance. This castle shape is very typical of the type found in medieval Europe, but you may want to experiment with more fantastical styles of castles and palaces. Different castle styles will have a different impact on the mood and the narrative of the world you are creating. 

To make the castle feel more attached to the game world, add some lines of Box Hedge Voxels underneath to build a green hill for it to be positioned on.

Use TAB to Enter Basic Editor Mode regularly to see if it is visible from the ground, and remember to look from several perspectives.

Also remember to check your parkour spots to make sure the player can’t see a castle floating in midair (unless that is something that’s possible in the physics of your world. Hey, it’s your game!).

Once you are happy with the size and general shape of your castle you can add some more detail. Remember, the castle is in the distance, so your main focus is to maximise the impact of the silhouette.

Start by making any spires or towers a more rounded shape. Use the Shape tool to draw a circle on top of a tower.

Drag the blue handles to extend the circle into a cylinder.

Press Enter to add the Voxels. You can move the same shape to any other towers to keep the same size and shape. This castle is very symmetrical, so this is a useful technique to save time.

Use the Eraser modifier of the Shape tool to hollow the towers. This effect will be important when you start to add the battlements.

Battlements are a very important feature for the look of a castle. To add battlements, select the Shape tool with the Eraser modifier, and draw a cuboid block on the top of a tower.

Extend the cuboid so that it will erase a distinct section of the tower. It should erase the front and the back of the turret. You might need to experiment with the size of your battlements by erasing a section, and then using TAB to see how this looks on the silhouette of the castle from the Basic Editor mode.

There is a noticeable battlement on the left turret, but the gap is too wide.

Once you are happy with the size of your battlement use the move tool to create a uniform set of battlements across the top of the towers of your castle.

Press TAB to view the silhouette of your castle in Basic Editor mode.

Tweak your castle silhouette to take into account some of the aspects of your reference document. For example, the tower sides can be trimmed to give a more dramatic shape.

You can also paint some features onto your silhouette using the Voxel Paint tool. Accurately modelling arrow slits with Voxels will be invisible at this distance, but to mimic the shadow created by the slit you can paint Onyx Voxels onto the towers. 

They are just about visible from the level, but these occasional small details makes the castle feel more solid and real.

Major features of the castle walls can also be added. Use the Extrude tool to add depth to the castle walls.

Use the Voxel Paint tools to draw the outline of features on the castle walls. In the example below, an archway has been drawn within the main gate area using the Onyx Voxel.

Use the Extrude tool to extrude or regress features, and use the Fill tool to make it an appropriate material.

The flag Meshes in the Library will be too small at this distance to be visible. Make a flag using wood and velvet Voxels

When you look at the flag from the level this really underlines the Capture The Flag game mode, and gives context to the other flags in the level.

Reusing Your Castle

The great thing about making a Voxel Mesh is that you can copy it and reuse it, just like you did with the houses in the level. However, this time you want to be able to change the colour of the flag. To do this you will need to duplicate it.

Tech Tip: Why Do You Need A Duplicate?

A Voxel Mesh contains a specific configuration of Voxels. When you place a Voxel Mesh in your game, you are creating an Entity which is linked to that Voxel Mesh. Whenever you edit that Entity, you are actually editing the Voxel Mesh. 

This means that if you change the colour of the flag in your castle Voxel Mesh it will change the flag colour for every Entity that originated from that Voxel Mesh (you can try this to see it in action). To make changes to a single specific Entity, you need to make a duplicate of the original Voxel Mesh, then you can make the changes to the duplicate without it affecting the original Voxel Mesh.

 Select the Voxel Meshes tab in the Library.

Right-click on the Castle Voxel Mesh and select Duplicate.

Call the new copy CastleB.

Add CastleB to the other side of the map.

Drag it into a suitable position, and change the flag colour to match the same colour as the other team.

Vary the distance and position of the new castle so that it’s different from your first one.

Playtest your game to feel the dramatic effect of being surrounded by castles. Great stuff!

Effects

Effects add wind, smoke, fire and other natural phenomena to your game level. Effects are great for adding realism and movement to your game world, and help make your game feel like it’s set in a rich world teaming with life. Just like lights, you can use Effects to attract a player to a feature or location, and to give them information about the level or the story of the game. For example, a smoke Effect might tell the player that something is on fire.

Open the Effects tab in the Library, and select the Smoke Chimney Effect.

Place the chimney smoke on one or two of the chimneys throughout the level.

They don’t need to all have smoke. Don’t forget, this is an abandoned village, so many of the fires will have gone out, or they might not have had one to start with.

Playtest your game to see the chimney’s in action.

Effects are particularly good for adding fire and flames to your game. Try building a fire using Meshes, Voxels and Effects.

Remove Unnecessary Meshes

Tech Tip: Optimisation

By now there is quite a lot going on in the level. To be a good game designer is managing everything you want to happen in the level, with the technical capabilities of the system and the game engine that the level exists in. This means you need to be considerate of the technical overhead of the level. You can do this by tidying up the level, removing Meshes and Voxels that aren’t in use, and by turning off collision detection on Entities that are not reachable.

Work around the perimeter to find and remove any trees that aren’t required to hide the wall. 

This tree is not visible because it is behind the other trees, so this is possible to remove.

Also, have a look around your level to see if you have left any Voxels or Meshes lying around that aren’t adding anything to the game. If unsure, try removing it and see if it makes a big difference. Everything in your level should add something to the game either narratively, for aesthetics or for gameplay.

Turn Off Collision Detection 

The physics engine within Crayta works very hard, performing thousands of computations every second to ensure that the simulated physics in your level work smoothly. The more physics enabled Entities you have in your level, the more difficult it is for the physics engine to keep up with the demands of the level. To avoid causing it undue stress, you can turn off the physics and collision detection on Entities which don’t need it.

Some Entities within your level would be strange if the players didn’t collide with them and walked straight through them, walls for example, but many things don’t need to. For example, the wall around the perimeter of your level acts as a barrier to stop your players from falling from the world, but the trees that are hiding it do not need to do this as well – they are purely aesthetic. Therefore, you should turn off the collision detection on the trees that are hiding the perimeter wall. Choosing which objects have collisions turned off will be down to you, but try to keep it believable (even if it is fantastical).

To turn off collision detection, select an Entity.

In the Entity Editor, uncheck the collisionEnabled checkbox.

You should also turn off collision detection on your castles – players cannot get to them, so they won’t need to be “collidable”.

Turn off collision detection on very small Entities that wouldn’t be noticeable if a Player walked into them. For example, the rocks around this firepit are very small, and the fire itself has collisionEnabled set to on, so the rocks can have their collisions turned off.

These books can have their collisions disabled also.

Add Your Own Tone Of Voice

In the Game Entity Editor, you can tweak many aspects of the gameplay itself, such as the text in the notifications of the game, the team names, the score and the game time. You should use these messages to further embed your theme within the game itself.

Click the dropdown on the Hierarchy menu and select the Game Entity.

The Game Entity contains the Script which is used to run the game logic, such as who is winning, who has the flag and so on. It is also in charge of the messages that get sent to the players when they join or leave, as well as the names of the teams. You can edit these messages using the Entity Editor.

Select the welcomeMsg in the Entity Editor by clicking on the Pen icon to edit the text.

A dialog box will appear, which contains the text from the welcomeMsg. Here you can see that the text gives a welcome message:

Welcome to the game *{name}*!

The *{name}* part of this sentence will be replaced with the player’s name when they enter the game. Change this text to fit the tone of voice that works with your game theme. For example:

Good morrow Sir *{name}*. I bid you welcome!

You can also include rules in this introductory message such as:

Refrain from profanity, or face exile from the realm.

Edit the other messages in the Game Entity Editor to fit your theme. Here are some more suggestions:

playerJoined: Hurrah! Good Sir *{name}* has joined us!

playerLeft: Alas! Sir *{name}* has bid us farewell.

You can also change the team names to better represent the theme of the game. For medieval factions, a good option is to choose words to do with animals, fighting and royalty.

Blue: Falcon Renegades

Red: The King’s Vanguard

Notice how changing the team names has suddenly created an entire story about a band of rebels trying to claim the throne for themselves.

And that’s it! Publish your level, invite your friends and let the battle commence!

Recap

Congratulations on completing this series of Level Design Tutorials. In this series you have learned the basics of creating an exciting and polished level for a Capture The Flag game. 

In this tutorial, you looked at:

  • Creating a backdrop for your game by building opposing castles
  • Using particle effects to add movement and intrigue to your level
  • Optimising your level to reduce the technical overhead
  • Customising the Game settings, to establish the theme throughout every aspect of the level.

Adding Polish

Practice the techniques introduced in this tutorial by adding the following to your level:

  • Add a tall hilltop with a monument and a church to the surroundings outside of the map.
  • If you didn’t add a fire to your level, consider adding one or two. You could make an area in the village where they gather to tell stories.
  • Take the narrative you have developed in this level, and explore some of the other game modes with the same theme.

Next Steps

Whilst the tutorials focused on the theme of a medieval village and knights, the same principles can be applied to any theme you can think of, and you can apply this to any of the inbuilt Crayta game modes. If you want to start building game mechanics from the ground up, you can take a look at the Scripting Tutorials, which you can use to establish some basic coding skills to build games in Crayta. 

Categories
Advanced Tutorials

Advanced Level Design 3: Lighting, skydome, and fog

Preface

Your level is really starting to take shape now, and many people would call it done. But great levels take the game production even further, and implement granular levels of polish and detail. It may seem small, but tweaking and adding to your level is how you make a good game great.

Introduction

Once the level has been designed for gameplay and aesthetic it’s time to ramp up the mood of the level. By evoking a mood, you reinforce the narrative of the game and start to build an aesthetic experience which moves your players emotionally. 

This tutorial looks at how you can tweak the global settings of your game to extend the world even further. You will also explore the crucial role of lighting in adding aesthetic, and guiding players through a level by highlighting important tactical positions and moving their eye away from some of the “behind-the-scene” functionality that we don’t want them to notice. 

Open Your Game

Start by reopening the level you are working for for this series of tutorials. If you haven’t got one, it would be worth learning some of the Advanced Editor tools and techniques before starting this tutorial, so run through that tutorial before continuing with this one.

Opening The Global Settings

On the right hand side of the screen is the Hierarchy which you have been using as a way of navigating between different Entities in your game. Select the World tab to open the World Settings.

You should see the menu changes to this.

Using this menu we can make some drastic changes to the world that surrounds this level such as moving the position of the sun, changing the colour of the sky and setting the surrounding environment.

Background Scenery

Refer back to your research document from the first level design tutorial, or search online for imagery relating to the theme of the level you are creating. Focus on the background of the images, what kind of world surrounds your level? You can use the World Settings to change the surroundings of your level to be more appropriate, and meet the needs of your theme.

Select the dropdown box next to outerHorizon and select Mountains.

You should see that your game is now surrounded with mountains.

Woah! You can also select the innerHorizon to be Mountains, although we won’t necessarily see the innerHorizon in this scenario as we have a forest of trees surrounding our game level.

Press TAB to change to the Basic Editor Mode and to get a feel for how the new outerHorizon landscape affects the feeling of your level:

It’s subtle, but players will unconsciously grasp that there are mountains poking out above the trees, tricking their brain into believing in a world beyond this village, and reinforcing the immersion of your world.

Creative Control: ImmersionImmersing a player in your game world is the holy grail of game development. If a player is truly immersed, they are no longer playing your game as a player, they are experiencing your game world as if they were there. So how do you remove the obvious barriers between your physical player and the virtual world.
Designing a believable game world involves grappling with a variety of different disciplines, from architecture to botany, but the more detail you add to your game, the more believable it is, and the more immersive it is. Keep adding detail to your level, refer to your research document, and build the world as if people live there, and as if the same forces of nature that affect our physical world also affect this virtual one.

Shaping The Sky

If you look up in the game editor, you will see the sun, high in the sky.

The time in the World Settings stipulates it is 2pm, and the world feels very much like the early afternoon somewhere bright and sunny. This is an abandoned medieval village, where something bad is going down, so it’s time for you to make the world reflect that.

Creative Control: Pathetic FallacyWhen you have a theme, and a narrative, for your level, everything in your game should reflect that (as long as it remains believable). A technique used by writers, directors and game designers alike is Pathetic Fallacy, which is a term used to describe how the natural phenomena (eg. the weather) in your world reflect the story of the game. It’s great for building tension, and helping your player feel your game narrative.

Firstly let’s make the weather a bit more miserable. Select the dropdown box next to skydomeAsset and select Rainy.

You will notice some clouds roll in over the sky.

Now, amp it up by changing the time of day. The time of day affects the position of the sun, and that affects a few things:

  1. How much ambient light there is in the game world, and what colour the ambient light is. The change in ambient light can affect how easy it is for players to see things in shadows or in the distance
  2. Shadows – dawn and dusk have longer shadows, whilst midday only has a small shadow underneath the subject, and night has none
  3. The colour of the sky – in the real world the suns rays refract in the ozone differently depending on the time of day, that’s why sunsets are always teamed with pinks, oranges, purples and even greens 

For the theme of this level it would be ideal to have good lighting for the combat, long shadows for atmosphere, and a time of day that a fight might break out. Let’s make it dawn. 

Position the Camera so that you can see both the sky and the ground of your level.

Change the start time hour to 6 and then use the mouse to click and drag on the minutes until the shadows in your level are large, but don’t affect the Players ability to see clearly.

Make sure to check your game world from multiple angles:

To further emphasise the mood, you can change the colour of the sky, which also has an impact on the ambient light, and gives the world a slightly different hue. Different colours can have a subconscious impact on how your players are feeling. If you are interested in how the different colours can change your mood, increase your heart-rate and even make you hungry, research “Color psychology”. Click on the OverrideSkylight checkbox.

Here you can change the intensity of the skylight, and also the colour. Click the coloured square to bring up a colour picker.

Aim for a colour like the one in the image above – morning light saturation, with just a hint of red. Red is exciting and can increase the feeling of conflict, but it is also not out of place at dawn. You should notice a subtle difference in the feeling of the level, and it should feel a bit more dramatic. Take a look at these before and after images below.

To add even more drama, you can move the direction of the sun to emphasise the shadows, and hide or show aspects of your level. Make sure to move around the level when you do this, and check your Players can still see each other. Click on the sunDirection slider, and move it left and right to choose a new angle.

You might find that moving the sun makes your sky colour more or less apparent (because the sun’s highlights will change), so feel free to tweak the two settings until the mood of your game feels just right.

Adding Fog

Fog is great for encouraging a feeling in your game, but it’s also a valuable tool for hiding the edges of the map.

Make sure your view is at ground level and click the OverrideFog checkbox in the World Settings menu.

There are several values you can change in the OverrideFog menu:

  • heightFogStartDistance – How far away from the player the fog will start.
  • heightFogFalloff – How high the fog reaches vertically.
  • heightFogDensity – How thick the fog is.
  • heightFogColor – The color of the fog.

The fog won’t appear until you have a heightFogDensity greater than zero (which is the default). Start by making the density something between 0 and 1, and then experiment with the heightFogStartDistance and heightFogFalloff to accentuate the mood in your level. It’s best to look at features in the distance of your level, to judge whether it’s improving the mood, or making the level feel unrealistic. As it’s dawn, you can experiment with relatively thick fog, and it should still feel quite believable.

Make sure that the start of the Fog is not noticeable. Here are some suggested values for the Fog in your level.

  • heightFogStartDistance: 3338.5
  • heightFogFalloff: 16.1
  • heightFogDensity: 0.3

Which looks believable and adds mood, especially around features such as rocks and buildings:

You can also change the colour of the Fog. Reduce the intensity of the white colour to help it feel a bit more subtle.

Continue to tweak until you are happy with the Fog. It looks good coming through the trees, so here are the values that I settled on:

Lighting Your Level

Now that you have added some mood to your level, you can step things up a notch by introducing Lights. Lights are really useful for ensuring that Players can see what they need to, whilst also invoking the mood that you are working hard to emphasise.

Open the Primitives tab in the Library and select Light.

When you move the mouse over the world, you should see that you can now place a Light.

Lights can be placed inside buildings to highlight them as places of shelter, and to ensure that it’s possible to see anyone taking advantage of the window cover. Move the view inside a building.

To make a Light believable, and feel like a part of your world, add some Props such as a table and a candle that will support the Light.

Add a Light to the candle.

To ensure that it doesn’t look like an incredibly bright halogen candle (which didn’t exist last time I checked), use the Entity Editor to change the intensity and colour of the light, so that it feels more natural, but still gives out plenty of light.

That’s better, but there’s still something odd about this candle. The light is passing through the bottom of the table, so underneath the table should be bathed in shadow. Click the shadows checkbox for the Light in the Entity Editor to turn on shadows.

Notice how this has created a much more dramatic interior to the building, and it feels more realistic.

Take a look from the outside.

The house now looks like somewhere that players can go and find cover, and it looks inviting. You can draw your players to different locations using lighting, but it’s a good idea to make sure that lights feel like they belong there, otherwise all your hard work when creating a believable level will be wasted due to unrealistic lighting.

You can add lights to your world in different ways, it’s a good opportunity to experiment and toe the line between realism and gameplay. Here are some possible suggestions.

Add a plank Prop to make a shelf on the wall to store candles and other artefacts.

Use man-made objects to light areas that supply good cover, and suggest alternative routes to the enemy base.

Use the lightspill from house windows to highlight areas or objects of interest.

Continue to explore lighting, and see what other effects you can find. Remember to playtest your game regularly, to ensure that your lights are having a positive impact on your gameplay.

Recap

Well done for completing Level Design Tutorial #3. In this tutorial you looked at invoking a mood in your level using some of the subtle effects available in the World Settings, and you explored lighting throughout your level to underpin your mood, but also guide the player and showcase elements of your level in a believable way.

Adding Polish

You can continue working with the techniques established in this tutorial by experimenting with the positioning of Lights throughout your level. 

Good lighting in games is an artform, and it only gets better with practice. Perhaps you could look at adding a variety of fires to your level, or add lights advertising the entrances to any inns or workshop buildings that you might have created in Level Design Tutorial #1.

Next up: Special effects and establishing a kingdom

Your game is oozing mood, thorough with detail and set within a beautifully dramatic landscape to boot. The last Level Design Tutorial will look at finishing touches to your level, including particle effects and building a narrative in the world beyond the edge of the level using an object called a Mesa, themed appropriately as a medieval castle.

Advanced Level Design #4: Particles and Optimisation

Categories
Advanced Tutorials

Advanced Level Design 2: Props

Preface

You have a rural medieval village, but it’s only a landscape and buildings that are empty shells. It might not feel like much, but you have a good starting point for a great level. The next step for you is to add Props.

Introduction

A Prop is a 3D Entity. Unlike Voxels, Props have been lovingly designed and modelled in 3D by Unit 2 game artists. There are literally hundreds to choose from and, on top of that, they can be rotated, stretched and positioned in infinite ways. This means there is a lot of creative freedom afforded to us with Props, and sometimes this can feel a bit daunting. But don’t worry, this guide will help you through and soon you will be a Prop master. 

If you’ve played around some of the games within Crayta, you may have experienced some clever uses of Props to give cover, create points of interest and hide areas of the level that you don’t want players to see. This tutorial will guide you through dressing your building, then expanding these ideas to dressing your level, and finally discovering some alternative ways of thinking about how you use Props.

Open Your Game

Start by reopening the level you created for Level Design Tutorial #1. If you haven’t got one, it would be worth learning some of the Advanced Editor tools and techniques before starting this tutorial, so run through that tutorial before continuing with this one (don’t worry, I’ll wait).

Hopefully you continued onto some of the extension activities and given your level a bit of “pizzazz” (like flower meadows ahh).

Finding Props – A Door

The first thing you are going to look at is dressing a building. Start by navigating your drone camera to one of your buildings, and use the selection tool (arrow) or the Hierarchy menu to select the building Entity.

You can tell your building is selected because it is highlighted in the Hierarchy and the Entity Editor is open for the Voxel Mesh which forms its base.

Using the Library on the left hand side, navigate to the Props section. The first thing we need to dress this house is probably a front door. There are a few different ways to find things in this menu, and some are more suitable than others. For the door, you can click the arrow next to Tags and choose the “door” Tag.

This will filter the menu to only include Props that have been “tagged” with the word “Door”.

As you can see, there is still quite a variety available to you. Another way we can narrow down the door we want is by using the list view which means we can see more Props at once. Click the list view button at the bottom of the Library menu.

This also expands the descriptive names of the Props, so it makes it even easier to find what you are looking for. 

In the Editor Your cursor will change to be holding the selected Door Prop. Position the door in the doorway to the house and left-click to place. 

Press ESC to change to the Select cursor.

You should notice in the Hierarchy menu that the door has been added as a child of the Voxel Mesh of this house. The good thing here is that if you now move or rotate the house the door Prop will stay in place and move with it.

Remove the filter from the Props Library by clicking the “-” next to the tag.

Adding A Window

Perform the same steps you used to find the door to find a window:

  1. Filter the Props Library to only display objects tagged with the word “window”
  2. Choose the Window (Narrow Wooden Frame)

Add one window Prop to your window hole. You may find it difficult to add a window into the gap you left for a window. This is because attaching something to mid-air is impossible. Instead, add it to a part of the window frame.

And then use the move tool to move it to the correct position.

Creative Control: Window Cover

You can choose to completely fill the window with a window Prop, but make sure to think about how this might be used for cover in the gameplay first. 

Every house has at least one window, so do you fill this hole, cover it completely, or half cover it.

Ask yourself, if I was a player inside the house, what can I see from the window? Where would an enemy need to stand to see who is behind the window? Are there any other gaps in this building that I can shoot through or be shot through? Finally, be careful to make sure the game is balanced – if a window offers one team an advantage how can give the other team an advantage too?

Select your window and press CTRL+C to copy, and CTRL+V to paste the Prop in the exact same position. Use the move tool again to move the second window.

You can open one of the windows by using the rotate tool. Select the window, select the Transform – Rotate tool, and then uncheck “Grid Snap”. 

Click and drag along the Z-axis (blue handle) to make the window open wide. The window will rotate around its centre point.

Once you are happy with the angle, use the move tool to move it into the correct position. 

You could leave it there if you don’t want your players using the inside of the buildings as cover. However, if you do, select your front door and uncheck collisionEnabled.

This means that players can now walk through the door and enter the house, and they can use the window for cover.

Dress the rest of the buildings in your level so that they all have windows and doors.

Dressing Your World

Dressing your world can feel a little bit daunting as there are lots of possibilities, and there are many Props to choose from. Also, whilst our research document can give us some ideas of general shapes of buildings and landscapes, it’s a little more challenging to pick out Props from imagery. How do you know which Props might be suitable for your level? This is exactly why Tags are so useful.

To start with, in the Props Library, expand the list of Tags.

There are many Tags. So far we have used Tags to find Doors and Windows, but Props are also Tagged with a theme. Our level is a fantasy, medieval, farming type village, which gives us a few different tags we can select to filter the Props to show only the suitable ones. 

Creative Control: Who Are These People?

Something worth considering when adding Props to your level is the story of the game. Everything in your level will tell your players something about this world and the people that inhabit it. If you fill it with farming gear it will feel like a farming village, if there are weapons everywhere it might feel like a barracks, and if there are crystal balls and skulls then maybe it’s a magical community. 

So far we have kept the level fairly simple, but now it’s time to further develop the narrative of the game through your choice of Props.

Placing A Point-Of-Interest – A Well

Use the Filter box at the top of the Library to enter the word “well”. You will see that it filters all the Props to only those with the word well in the name (WELL and JeWELLed).

Select the Well from the Props Library

Creative Control: Placing Props

When you need to position something in your level, it’s a good idea to think like an inhabitant. Whatever Prop you choose, stop and think where would it go in real-world medieval time? For example, it’s likely the well would be somewhere nearby the village, easily accessible. 

Then, think about the gameplay. A well offers light cover, and you can shoot through some parts of it. Make sure it gives both teams a fair opportunity.

Place the well in your level.

You can use some of the Voxel techniques you learned in Level Design Tutorial #1 (painting and adding Voxels) to make sure that the well feels like part of the level. Maybe there is some mud due to the loading of water, or unkempt grass and flowers that have sprung up because of the fertile soil around the base of the well. You can call this technique “bedding it into the level”.

Building A Story With Props

One of the great things about building your own game is that you can choose what the story of your game is. Just bear in mind the type of game that you are making, and some Level Designers find it helpful to use the type of game to drive the narrative of the level. Capture-the-flag is a combat game, so in this level you could build a narrative about a surprise attack – all the villagers have fled! Items in the level can appear as if they were mid-use, but have been left in a hurry, or dropped in the middle of a job.

Browse the Props Library, and pick some items that you could include as points-of-interest. Build them into the narrative of the level, by making them “dropped in the middle of a job”. Remember to use Voxels to bed the Prop into the level, so it feels like part of the world, rather than added on top of the world.

Here are a couple of ideas you might want to add:

Here are signs that a person was gathering hay when the combat erupted, and they dropped the wheelbarrow and ran. Notice you can build some additional cover and maintain the narrative at the same time. The wheelbarrow and the hay bales offer two sets of cover.

A woodchopper midway through chopping some wood.

Bury some of the logs beneath the ground, to make different sized logs. You can also rotate them, and position them in a natural way. I have also used log voxels to create a “chopping plinth”.

Not everything has to be “dropped in the middle of a task”. This wheelbarrow wasn’t in use, and this looks like the place it is kept because the grass doesn’t grow where it is usually stored.

Add some buckets to the well – it’s used for villagers to gather water, so it makes sense there are some buckets nearby. If one is on its side, the players can fill in their own story about why.

Barrels are nearly always acceptable to put in a medieval world.

Groups of barrels can offer some medium sized cover.

There is a road running through this medieval village, and perhaps someone in the village knows how to repair and build carts.

Like barrels, crates are very versatile, and will still fit the narrative here. Move and rotate one or two of them with Grid Snap unchecked to maximise the realism. These crates also offer players an aspect of “parkour” to the level – skilled players can use these to get onto the roof, which has excellent line-of-sight, but is very exposed.

A medieval village might have had one or two hunters, and they will be using bows in order to capture food for the town. Targets don’t always have to be for combat, it could be for training young hunters, or just for a pastime.

Don’t forget to playtest your game, to make sure that the cover feels suitable, and to check lines of fire and combat potential of your level.

Enclosing The Level With Scenery

Now that you have built a loose narrative for your level, the last aspect of this tutorial looks at building walls to your level, and disguising them using natural scenery. Scenery includes rocks, trees, plants and other natural phenomena that will make this feel like a living, breathing world. 

To enclose the level we will make the village situated in a clearing in a forest. To build the walls, use the Logs (Vertical) Voxel to encircle the entire level. You need to make the logs at least 8 Voxels high to ensure the players cannot jump over them.

Start by using the Extrude tool to make the sides 1 Voxel wider.

Use the shape tool to draw a Cuboid of Log (Vertical) Voxels along the perimeter. Use the blue handles to raise the height so that players cannot jump over it.

Test your game and make sure you can’t jump over the exterior wall.

Surround your level with a wall of logs.

Now to disguise this hideous wall! You are going to use some of the fauna that is available in the Props menu to hide this wall, although it will still ensure your players don’t fall off the edge.

Ensure you have the Props open in the Library. Use the filter textbox, or the Tags to find trees.

You can drag the edge of the Library out to make it wider, and see more tree Props.

It may seem like choosing any tree would work here, but there needs to be some consistency between the world you are creating and the things that inhabit it, and that includes trees. You can use almost any tree in a world set in the present day, but when it comes to historical places you have to be a bit more careful.

The village is generically medieval, and the style of buildings made in this tutorial fit into a very westernised, European style of medieval. As such, the best trees for this level are going to be ones that would have been commonplace, and grown wild, in medieval Europe. For quick reference, here is a rundown of the general area of origin for some of the trees in Crayta:

NameOrigin / Climate
AcaciaAfrica
AppleAsia, Europe, North America (after colonial period)
BambooAsia
BananaAsia
BaobabAfrica
CedarAsia / Europe (high, mountainous regions)
CherryEurope, West Asia, North Africa
CypressNorth America, Africa, Australia, Europe (warm, mediterranean regions)
Date PalmNorth Africa, Middle East
Douglas FirNorth America (introduced UK 1800s)
EucalyptusAustralia
FirEurope, North America, Asia
JoshuaNorth America
JungleJungles
Mountain AshEurope, North America, Asia
OakEurope, Asia, North America (after colonial period)
PalmTropical countries
SequoiaNorth America – California
TopiaryGardens in Europe 1500s onwards, everywhere modern day
Weeping WillowAsia, Europe, near fresh water
YewAsia, North America, Europe. This style is more likely to be modern day.

As such, we can nail down the varieties we can use here are:

  • Apple
  • Cedar
  • Cherry
  • Fir
  • Mountain Ash
  • Oak
  • Weeping Willow

This tutorial only uses Oak, as it is a common tree in woodland and offers good foliage for hiding things. You can use a variety, or pick one and stick with it.

Make sure you have Grid Snap turned off and Collision turned off whilst placing these first trees, as these will be mostly used to disguise the log wall.

Place an oak tree Prop next to the wall.

Use the move tool to move it back to embed the tree within the log wall. 

Now move the tree down so the foliage is poking through the wall.

Don’t worry about making it perfect at this stage. By replicating this around the wall the overall effect will feel like the edge of a very dense wood.

Continue to place trees along the log wall. You can copy and paste the tree and use the X axis handle (red handle) to move the tree across. Make sure to vary the position slightly (higher/lower, forwards/back) and rotate the trees randomly to give the illusion of a wall of foliage. Don’t forget to loosely follow the contour of your land.

Once you have completed one wall, put your camera at head height and check to see if there are gaps where the player can see the wall. If there are any really obvious sections of wall at person height then add another tree to cover them, don’t be afraid to lower the tree significantly into the ground to fill the wall with foliage.

You can safely ignore most of the higher sections of the wall, as these will be covered by trees in front of it.

Proceed to do the same across all the log walls in your level. To save time, you can make a copy of these trees to paste over the wall on the other side. Click the first tree on the Hierarchy menu – this was treeOak1 for me.

Then hold SHIFT and select the last tree you placed in the Hierarchy menu (treeOak33 for me).

You should see you now have all the trees along the wall selected. Press CTRL+C and CTRL+V to copy and paste them, and then use the move tool to move them to the opposite wall.

You can do this again, and use the rotate tool to fill the remaining two walls.

Check your walls for any missing trees or really obvious sections of log walls.

Fix any gaps by adding another tree or adjusting the ones you have already.

The effect in the end should look like your village is in a clearing in a forest.

To polish this effect, add some more trees on the ground just in front of the log wall. Remember, forests are rarely in a straight line, so vary the position and rotation of your trees a little bit (with Grid Snap turned off) to make sure that they simulate natural growth. 

You should also add one or two trees interspersed amongst the village – medieval villagers did not chop necessarily chop trees down if they didn’t need to.

Remember to vary the rotation of your trees.

Playtest your level to make sure that it feels like you are in a wood clearing. Check for a balanced gameplay, and for a world that feels real. Keep tweaking the level and make small adjustments to ensure that it is telling the story of the level as much as it can, and giving your players opportunities for an exciting and interesting challenge.

Recap

Great work. You have now started to build a world and an embedded story within the level. There are lots of inventive ways to use the Props in Crayta to add drama or intrigue to a level. How resourceful can you be? In this tutorial you practiced the following techniques:

  • Navigating the Advanced Prop Library of 500+ Props
  • Dressing a building in your level
  • Dressing your level
  • Using Props as points of interest to guide the action and balance the gameplay

Adding Polish

You can continue working with the techniques established in this tutorial. Here are some further phenomena you might want to consider adding:

  • Dress the inside of your cottages – who are these people? How did they live? Use your research document from tutorial 1 or go and investigate some more.
  • Add rocks and other natural phenomena around your level, think about how they might give players some cover or create visual obstacles, and what would naturally occur in the real world.
  • Explore the range of Props further. Some Props in the library could be used in different ways by sinking them into the Voxels like you did with the trees into the log walls – for example, you could use the top of a wardrobe as a decorative bar in a tavern.

Next up: A world beyond the boundaries

Now that you’ve dressed your level and developed a narrative it’s time to ramp up the mood of your level, and really embed the drama. In the next tutorial you will look at adjusting the skybox, global lighting and adding further lights to evoke mood throughout your level.

Advanced Level Design #3: Lighting, Skydome, and Fog

Categories
Advanced Tutorials

Advanced Level Design 1: Voxels

Preface

How do you make great levels that are fun to play, believable and also look good too? This series of tutorials is focused on making a single Capture The Flag game, and working with Crayta’s Advanced Level Editor to shape and dress a level that is aesthetically pleasing, but that also offers some interesting gameplay opportunities.

The Advanced Level Design tutorials are designed to introduce you to some of the advanced level design tools available in Crayta, and to give you the skills and the confidence to theme and develop your own levels. There are some additional activities at the end of each tutorial to further develop your skills, and to make your game more dynamic and interesting.

Introduction

Level design is an art, and there is not necessarily a right-or-wrong way to make a level. Instead, this first tutorial aims to show one good way to start making a level that is often used by professional game designers. You will take a simple game mechanic, decide on a theme to work with, and start to shape a themed landscape that offers opportunities for some interesting gameplay dynamics. Later tutorials will look at dressing the level and adding rich detail. Let’s get going.

Create Your Game

When you’re designing a level, you need to keep two things at the forefront of your mind:

  1. How will this affect gameplay?
  2. Does this feel believable?

Level design is a constant balancing act between these two things, and when you get it right, the level will look and feel great to play. Sometimes you will make level design choices based on gameplay, sometimes it will be aesthetics. 

To start, open Crayta and create a copy of the Capture The Flag game. You will be using this as your template for these tutorials, but you can use many of the same techniques regardless of the game type. You will be greeted with the following screen:

Press TAB to enter the Advanced Editor Mode.

Game Breakdown

Capture The Flag is a team based game, where players must run to the other team’s base, grab the flag, and return it to their base. Each time they do this, they score a point. When the timer reaches zero, the team with the most points wins. Sounds easy? There is one thing that makes it slightly more challenging – you can kill each other:

  • If you get killed, you will respawn at your base after a time penalty.
  • If you get killed whilst holding the flag, you will drop the flag, which means either team can pick it up. If a team recaptures their own flag, it returns to their base automatically.

Test your game and play with the mechanic to get a feel for what the players need to do. When you are happy that you understand the basic premise, return to the Advanced Level Editor.

Game Parameters

Each prebuilt game mode includes a list of parameters that you can change to completely customise the gameplay of your level. The game is coordinated by a “Game Script” which you can find by clicking on “Game” within the dropdown in the Entity Hierarchy. 

The game is quite short at the moment. You can adjust this with the maxPlayTime Property. Lengthen the game time from 1 minute to 5 minutes. Within the gameScript, find the “maxPlayTime” Property, and change this to 0H 5M 0S:

Test your game. Once the lobby has concluded, you should find the game timer now counts down from 5 minutes.

Creative Control

The gameScript gives you many options to change the game parameters. This gives you the opportunity to design your game right down to the core mechanic. You can regularly revisit this Script and make tweaks to improve your gameplay.

Researching A Theme

Coming up with a theme can be great fun, but using it throughout your level design can be a little challenging. For this tutorial, we will take the game type as the inspiration for our theme. Flags. Flags make me think of a mysterious history, a dark fantastical time, a time of knights and noble deeds and glory, and flags. Two warring factions are locked in eternal combat, fighting to lay claim to a crucial, yet sleepy, town. By capturing the flag, they assure their complete dominance over the opposing clan, and when the battle is over, the winner rules the realm. 

To develop this theme, a good idea is to create a research document, and then fill it with imagery of the type of world you want to make, and the feeling you want to give to your player. The process for this is simple, find somewhere which you can use to store your images (a Google Doc is a good start), and search online for images relating to your theme. For this theme, I might search for the following words and phrases:

  • Medieval village
  • Knights
  • Wilderness

Copy and paste images that reflect your theme into the document. The process of doing this helps you to fine-tune your theme, and gives you something to refer back to as you develop your level. Write a note to remind yourself of ideas triggered by the image, and give a reason why you have added that image in particular. For example “a narrow bridge over a canyon – it’s a shorter way across than going around, but limits your movement making you easier to trap”.

Creative Control: What Does This Add To The Game?

The level itself is a useful tool that can help players to achieve their aims, progress through the game and have an enjoyable experience. Each aspect of your level should perform one or more of the following actions:

  1. Teach a new game mechanic
  2. Provide a memorable moment of gameplay
  3. Supply the player with a reward such as a powerup, or a new weapon
  4. Provide a pleasant visual vista and/or a memorable area that helps the player orient themselves in the level

Knowing why you have added it to the level will also give you the chance to make sure it performs its task well, and don’t be afraid to modify or remove elements that are not meeting one of these criteria.

Once you are happy with your document, and feel like you have plenty of material to refer back to, return to the Crayta Advanced Level Editor.

Mapping Out The Level

By holding right-click on the mouse, you can use WASD and the mouse to move around. You can also use Q to move down, and E to move up. Move the camera back in your level so that you can see the entire playmap.

You can use the Fill Bucket tool to turn the white Voxels into grass. To do this, click on the Fill Bucket icon at the top of the screen. Then, select the “Grass (Short)” Voxel in the Voxel Library. Click anywhere on the terrain Voxel Mesh to turn it into grass.

You should also give your players a decent sized play area. To extend the map, you can use the Extrude tool. The Extrude tool can be used to extend a Voxel Mesh in any direction. Select theExtrude tool at the top of the screen (next to the Fill Bucket). Hover over one edge of the Voxel Mesh and you will see a strip of Voxels highlighted in blue under the mouse cursor. Click and drag the mouse to extend the Voxel Mesh. Make your level a bit longer, and a bit wider using the Extrude tool.

Remember to test the game regularly until you are happy with the size of the level.

Now it’s time to create a basic level map. Ignoring gameplay for a second, the first thing we want to do is build a familiar topography for a medieval village. 

Sketching The Level

Using the research document, you can see that many fantasy villages are placed in a green space, near a water source and near a forest (close proximity to natural resources would have been very important before everyone drove around in cars). This map will put each of the bases a different hilltop, with a village between them. 

Firstly, select the Grass (Wild) Voxel from the Voxel Library. Select the Pen tool and click on the Paintbrush modifier. Increase the size of the tool to 20 x 20 x 1. You can use the Paintbrush Pen to sketch a basic topology of your map. Start by painting two new areas for the bases. For the Capture The Flag game, the base location is important. They should be balanced, so that neither team is at an advantage, and easily visible, so that all the players know where to go. A good start for new base locations is at opposing ends of your map.

To ensure it is intuitive where the players need to get to, these bases will form two hilltops, and will be eventually decorated with objects of the teams colours. In order for our level to feel believable, we need to think about why these two hilltops might exist..

Creative Control: Take Inspiration From The Real World

To make a believable level, even a fantastical one, we need to draw inspiration from the real world. Here you are going to separate two hilltops at similar heights, so you have a couple of believable options to choose from. 

You could use a medieval path, which would likely have taken the easiest route between two hilltops, i.e. the flat space between them. Alternatively, if you wanted to separate the hilltops with a water feature, a river might have eroded a valley between the two hilltops.

Use a different Voxel (I’ve used Gravel) to separate your hilltops with a line that can give a general flow to your level. This will help players feel like this is just one snippet of a larger world, and gives you a guideline to build around.

Creative Control: Start big

Leonardo da Vinci famously stated “Art is never finished, only abandoned”. This is true for levels and games too! We are in the early stages of a level design, and there is a lot to do. The trick here is to not be too precious with the small details. Once you have built up a level map you can refine it later, and make it perfect. You need something to work with first, and sketching out the level is the first step in the process. So be bold! And don’t be scared to make mistakes, sometimes they can lead to the most interesting aspects of your level!

Contouring

Contouring is a great technique to build aesthetic and functional topography. Contouring uses two tools – the Pen tool and the Extrude tool.

To start, select the Pen tool and change it to a square. Ensure the Paintbrush modifier is selected, but change the size of the block to 3 x 3 x 1. Draw a line joining your hilltops to the edges of the map, loosely following the direction of your pathway.

Now you can add some more contours between this key line and the pathway. Add 4-5 contour lines between the base and the line in the middle. Add a few contour lines behind your hilltop also. Make sure that none of the lines touch each other, there must always be a gap between them. Also make sure that they reach the edge of the map.

Creative Control: Contouring

Look at any standard Ordnance Survey map and you will see contour lines. These are lines that show the map-reader the height of the land. Looking closely, you will notice that they are never straight, and they are never the same. Also, the closer they are to each other the steeper the land. Take these points into consideration when you are drawing your contour lines.

Once you are happy with your contour lines do the other side in the same way. 

Once you have finished drawing all of your contour lines it’s time to grab the Extrude tool and turn these lines into hills.

Click the Extrude tool. The Extrude tool raises or lowers a group of Voxels that share type. For example, each of the Grass (Wild) you painted into contour lines are now their own group. Use the Extrude tool to raise the line of Grass (Wild) closest to the path by one block.

Now raise the line of Grass (Short) behind this by two blocks. Then the next contour by three blocks, and so on. You should see a hill forming. If you realise that a line doesn’t reach the edge of the map, or that it is touching another line, it’s easier to return the height to the base level and use the Pen tool to revisit the line to make sure it’s perfect, then try Extruding again.

Once you have reached the edge of the map, repeat the process on the other side

Great! You have created a valley using contouring. To finish the valley, use the Fill Bucket tool to fill each of the lines with the same Short Grass Voxel.

Finally, tidy up any Voxels that you think look a bit out of place.

Moving The Bases

Once you have created your landscape you can reposition your bases to the hilltops you made. To do this, first select one of the flags and move it to the hilltop.

Do the same with the Locator. Make sure that you move the Locator “start1” to the same hilltop as the Prop “flag1”.

Select the Eyedropper tool. Clicking a Voxel with the Eyedropper tool selected will equip your Pen tool with the Voxel type automatically selected. Click the white material that forms the old base. Then select the shape tool, and the Paintbrush modifier. Paint a square of the same size as the original base under flag1/start1.

Use the Eyedropper again to select the blue plastic that surrounds the original base. Again, use the shape tool with the Paintbrush modifier to replicate the original base by drawing a coloured border around your white square.

Now select the Fill Bucket tool and the Grass (Short) Voxel from the Library. Fill the old base with the Grass Voxel to remove it completely.

Test the level and you should find that you now spawn at the blue base that you moved to the hilltop.

Move the red base to the opposing hilltop using the same technique.

Creating Template Voxel Meshes

Now that we have a fantastic topology for our game we can get to work on building the village. 

Start by moving your character to an empty space within your map. To do this, hover your cursor over a clear, flat location and press R. Your character will appear where your cursor is. You will use your character for a sense of scale when building your Voxel Meshes.

To create a new Voxel Mesh, use the Library to navigate to Voxel Meshes. You will see that one already exists in here – your terrain. Click Create New Asset to create a new Voxel Mesh. Name the new Voxel Mesh “House”.

Select the Voxel Mesh in the Library.

Click anywhere on your map. You will see that every new Voxel Mesh starts as just a single 1x1x1 block. By ensuring that the Voxel Mesh is selected in the Hierarchy menu (on the right), you can build on this block and it will all be part of that particular Voxel Mesh.

Select the Shape tool, this time with the Add modifier selected. Select the Brick (Medieval) Voxel. Draw a floorplan for your house with a reasonably sized rectangle. It doesn’t need to be huge, as this is just a small peasant house in a medieval village.

Press Enter to add the floor bricks. Before deselecting the rectangle, turn on the Eraser modifier for the shape tool. Bring in the sides by one block each. Press Enter and you now have a floorplan for your house.

Select the Extrude tool and Extrude the floorplan up to above the height of your character.

To make the roof, use the Shape tool to draw a line of Voxels across one end of your house one Voxel wide. Select the Steps modifier. Now increase the height of the line and you should see that it automatically creates a sloped roof shape. Press Enter to add the blocks.

Classic peasant houses tend to use “thatch” which is a natural roofing material made from hay. Use the Library to select the Hay Voxel. You can type “Hay” into the Library Search Bar to save time.

Select the Hay Voxel, then select the Pen tool. Make sure that the Add modifier is selected and set the size of the Pen tool to 1 x 1 x 1. Create a single block layer of Hay resting on your sloped roof. You might want to add a small overhang to either side of your roof also.

Once you have marked up your roof, you can use the Extrude tool to extend it to the other side of the house.

Make sure to add overhang to the roof on either side to give the house a way for any rainwater to run off. No-one wants soggy peasants.

Great! To finish your house, use the Shape tool with the Eraser modifier to remove blocks for doors and windows. Remember, you are making a game which includes some combat, and that these buildings will form major parts of cover. Windows can offer a major advantage to clever players, as they give partial cover. Think about the aesthetics (how it looks) as well as how the impact on gameplay when you’re shaping and adding detail to buildings and features.

Add some finishing touches to your house, such as some grass around the bottom so that it feels embedded within your level. Make sure to add the grass to your House Voxel Mesh, and not the Terrain Voxel Mesh.

Great! You have made a house template. Creating a village is now simply a case of adding a few houses to your level. Select the House Voxel Mesh in the Library.

Add some houses to your level. If you look in different directions when you add them you can add houses at different angles. In your research document, you might notice that medieval villages didn’t tend to have an ordered grid system (they didn’t have town planners like we do now) – buildings were made where their owners wanted them to be. So feel free to dot them around your landscape in small clusters of two or three. Remember to follow the line of your level.

Test your game often and get a feel for your village. You can move, rotate and delete buildings that don’t feel quite right as you wish.

Recap

Great work. You have established a small village in a valley. In this tutorial you practiced the following techniques:

  • Sketching out a level map.
  • Using contours to create a believable topology.
  • Making use of a variety of Advanced Voxel tools such as Shape, Pen, Eyedropper and Extrude.
  • Changing the function of the tools using a mixture of modifiers.
  • Creating a new Voxel Mesh to make a reusable building template.

Adding Polish

This is just the beginning of your map. You can continue working with the techniques established in this tutorial. Here are some further phenomena you might want to consider adding:

  • Your cottage is made using Brick (Medieval), but there is a more suitable Brick (Cottage) in the Voxel menu. Use the Fill Bucket tool to change the brick to one template, and you will see it replaces this for all templates.
  • Add some more detail to your house Voxel Mesh such as a chimney and paint a floor material
  • Create another house template, and dot these around your map also. Adding variety to the buildings on your map will make your world more believable and immersive.
  • A village would usually have some simple amenities such as a place to congregate and socialise, and a place to buy things. What other buildings could you make? Use your research document for inspiration.
  • Use some of the more decorative Voxels throughout your level. Add Grass (Wild) and Grass (Meadow) throughout to create variety. Think about how these phenomena would occur in the real world when choosing where to place them.

Next up: Props

Now that you’ve had a look at some of the more advanced techniques in level building it’s time to think about dressing your level. To do this, you will be using the Props Library. Head over to the next tutorial to discover more.

Advanced Level Design #2: Props

Categories
Advanced Tutorials

The relationship between Player and Default camera

Preface

In most 3D game engines the concept of a camera is quite common. Cameras are the devices that capture and display the world to the player.

Crayta provides this mechanism: a default camera with a number of customization options to easily achieve your desired gameplay camera and the option to spawn any number of secondary cameras to be further used.

In this tutorial we will explore the relationship between the default camera and the player, and also how to create and use additional in-game cameras.

If you are coming from a Unity background you will be familiar with camera game objects.

What’s different in Crayta is that the default camera is directly attached to the Player entity. The default camera comes with ready to use controls for a first and third person camera setting.

In Unity you could do something similar either with implementing your own solution in code or using a starter kit.

Default Camera

In Crayta the default camera is basically the Character entity automatically spawned in the game world from the Player template, so it won’t be exposed separately in the Entities World Tree.

Crayta provides a default first or third person camera with a number of settings to customize for each type.

Camera Primitive

Additional cameras can be spawned in the game world to be used later during game play for cutscenes, level previews, as a background when showing game results etc.

Camera entities spawned in the world remain inactive until activated from a script.

How to select a camera?

When starting any Crayta game your spawned User entity in the game world automatically sets the selected camera to the default. And that would be your Character entity since in Crayta:

The default camera is the character entity.

At any point in a Crayta script you can change the selected camera to any other camera entity using the following code:

userEntity:SetCamera(cameraEntity)

You can also specify an optional second parameter as the transitionTime in seconds. That will automatically animate the view from the current camera to the newly selected one:

userEntity:SetCamera(cameraEntity, 3.0)

At any moment you can fallback to the default camera by calling the same method with no parameters:

userEntity:SetCamera()

And lastly you can query the active camera using a similar method:

userEntity:GetCamera()

If the default camera is selected, the Character entity will be returned. Otherwise a camera entity will be referenced.

It’s a simple and powerful mechanism that allows you to present dynamic views of your game world to the player.

Categories
Advanced Tutorials

Creating Voxel Meshes using Volume Select

Preface

Crayta provides a powerful voxel building system allowing you to create big and varied game worlds. You can quickly create your game level surfaces to start testing your gameplay and later go back and add cosmetic details easily.

In this tutorial we will explore how Volume Select, a Voxel tool available, works to edit and extract parts of a Voxel Mesh. Which you can later reuse in other parts of your Crayta world.

What is Volume Select?

When creating a new Crayta project you will find a single Voxel Mesh, in the form of a ground floor, already placed in the world for you. If you start drawing voxels on this surface, the voxels created will be automatically added to that original Voxel Mesh.

This stone door that we created is nice but what if our game requires moving it to a different location? Volume Select allows us to select a number of voxels from a Voxel Mesh to execute a number of methods on them:

Clicking Volume Select on the Voxel Tools toolbar allows us to create a selection volume in the 3D view to include our voxels. You can add a selection volume and further edit it using the gizmo to precisely select the required voxels.

Then you can execute one of the following methods:

  • Extract, creates a new Voxel Mesh from the selection containing the selected voxels. This will also have the voxels selected removed from the current Voxel Mesh.
  • Move, allows you to move the current voxels in the world, inside the current Voxel Mesh.
  • Duplicate, allows you to create a copy of the current voxels, inside the current Voxel Mesh.
  • Clear, will delete the selected voxels from the Voxel Mesh.

Let’s take a look at how each method works.

Moving Voxels

Using Volume Select to select a number of voxels and pressing Move will render the move gizmo at the center of the selected volume.

Using the gizmo you can move the voxels around and when finished pressing Apply on the toolbar will complete the action.

Duplicating Voxels

Duplicating Voxels is very similar to moving Voxels, with the only difference when finished moving the voxels around a new copy will be created.

Clearing Voxels

Clearing Voxels is even simpler: selecting Voxels with the Volume Select tool and pressing Clear will automatically remove those voxels from the Voxel Mesh.

Extracting Voxels

Extracting Voxels is a powerful tool that allows us to easily reuse voxels to enhance our game level.

When selecting Voxels using Volume Select and pressing Extract the output will be a new Voxel Mesh and Entity added to your project.

The new Voxel Mesh created will automatically be named based on the name of the original Voxel Mesh. A good practise is to remember to name the new extract to something sensible, helps a lot when starting having a lot of Voxel Meshes in the same level.

You can now easily reuse this new Voxel Mesh to make copies of the stone door in your level.

At any point you can merge back this new Voxels to a parent Voxel Mesh entity.

To do that move the Voxel Mesh entities, to be merged, as children to the parent Voxel Mesh entity. Right click on each entity and select Merge To Parent.

Each merged entity will be removed from the Entities Tree and the Voxels merged to the parent Voxel Mesh.

This is a powerful system to easily create levels and interesting worlds for your game.

Categories
Advanced Tutorials

Script variable scope

Preface

When building a game in Crayta you will often need to store information about the state of your game; game score, current level, number of enemies, etc are all examples of information you would store using variables. You may use these variables while coding your Lua scripts to build working blocks of code, much like you would in any other programming language.

While it is very easy to declare variables that hold supported Lua data, their scope will be different depending on how and where we declare said variable.

In this tutorial we explore the different scopes available for Lua variables in Crayta.

Variable scope is a subject of study and practice in any programming language. Something that the developer has to understand and use accordingly.

In Unity with C#, the scope of a variable or property is set using special keywords, public and private. These define if other script classes have access to variables or not.

In C# you can’t define global variables, since everything has to belong in classes.

Local Variables

In Lua there is a keyword used to declare variables with a local scope, named local. Local variables have their scope limited to the block where they are declared. A block is the body of a control structure, the body of a function, a for loop etc.

Here is an example to illustrate this:

function CollectableScript:Init()
  local name = self:GetEntity():GetName()

  if name == 'cottageChair' then
     -- works, variable name is available since it was declared in a parent scope
     local nameLowerCase = name:lower()

     -- works, variable nameLowerCase is available since it was declared in this scope
     Print(nameLowerCase)
  end

  -- doesn’t work, variable nameLowerCase not available in this scope
  Print(nameLowerCase)
end

Global Variables

Global variables in Lua do not need declarations. You simply assign a value to a global variable to create it. This variable is available in any scope of this script.

For example let’s test this code:

local CollectableScript = {}

function CollectableScript:Init()
    
  local name = self:GetEntity():GetName()

  if name == 'cottageChair' then
      myGlobalVar = 'aGlobalValue'
  end
End

function CollectableScript:OnInteract()
    Print(myGlobalVar)
end

If we assign this script to a number of entities, with one of them named cottageChair, then each time we interact with any of these entities we will get aGlobalValue printed in the console.

A global variable has the same value across all instances of the script.

Global variables have a greater performance impact compared to local variables, so as a preference local variables should be preferred. In addition global variables produce poor code architecture, breaking abstractions and object oriented paradigms, making maintaining a codebase difficult.

Self Variables

Crayta uses an object oriented approach in writing reusable code. Each Lua script contains the definition of a class-style type that can be reused (instantiated) by any number of entities that have a script component of this type attached.

The methods declared in this script will run on a different context each time. That of the entity the script is attached to.

For this reason it is quite useful to be able to declare variables that can be used by any method of the same script, but not between script instances.

Crayta makes available in any script a special variable named self. We can use the dot notation to declare variables that are available on a specific script instance this way.

Let’s rewrite the previous example to accomplish a different task using self.

local CollectableScript = {}

function CollectableScript:Init()
    
  local name = self:GetEntity():GetName()
  self.nameLowerCase = name:lower()

end

function CollectableScript:OnInteract()
    
    Print(self.nameLowerCase)
end

Now if we attach our script to a number of entities, whenever we interact with one of them we will get their name printed in lowercase to the console.

Using self.nameLowerCase we make sure that we declare a new variable unique to each script instance executing.

Accessing from other scripts

Local and global variables are accessible only within the same script. On the other hand variables defined using self can be easily accessed by other scripts. Variables in Lua can hold not only data values but also references to functions.

This is powerful and allows you to easily extend your code to read data and methods found in other scripts.

Here is an example of how we can access the nameLowerCase variable from another script:

local AnotherScript= {}

AnotherScript.Properties = {
      { name = "collectable", type = "entity"}
}

function AnotherScript:MyMethod()
    
    Print( collectable.collectableScript.nameLowerCase )
end

We can access the script instance of a script with its name, on any entity that has it attached. Any variables or methods declared on self are available now using the same notation.