Professional Documents
Culture Documents
In this lecture, we are going to create a new game project for Project Boost.
This is going to involve making our player and writing our first script in Godot dedicated
language
script.
We want to return to the project manager so that we can create Project Boost.
In the top bar on the left, click the project menu button and in the dropdown select Quit to
Project
List.
This is going to exit us out of that project and return us to the project manager.
From here, we can click the new project button in the top right.
For the project path, I'm going to select the folder we created in the introduction for my games.
And we can click the Create Folder button in the top right.
With that all set up, we want the default forward plus renderer and we can click Create and
Edit.
The first thing we're going to want to do is make a change to our editor settings.
In the top bar on the top left, click the editor button and from that dropdown select Editor
Settings.
This will restrict the tree view on the left and show us this completion option that if we click
on,
This is already enabled because I enable it in every project I run, but you'll just want to click
the
check mark next to the word on and it will enable add type hints.
If we hover over this property, it will tell us a bit more about what this property does.
But essentially when writing scripts, Godot will now automatically add variable types to
variables
we work with.
Now we've not got into what variables are yet, but you'll need to trust me a little bit that this
will
make our coding more precise when we get to writing our scripts.
In the top left in the scene tree, select 3D scene as the root node of our scene and then rename
that
node to player.
It will be the main character we're controlling, and it is what we are going to attach scripts to.
You can declare a list of things you want to happen at specific points, and then the script will
make
Look at the scroll and click the scroll with the little green plus in its bottom right to attach a
script
to it.
Or you can right click on the node and select Attach Script.
It's worth knowing one node can only have one script attached to it, but in a scene, any number
of
We're going to attach a script to this player node and it will open the Attach Node Script
dialog.
One thing we're going to want to do is enable this template option, which is just going to set
up our
One thing that's worth noting is Godot does support a bunch of different languages.
Gdscript is the built in and default language, and it really has a bunch of very nice features that
It's going to default the path for this script file we're creating to have the same name as the
node
we attached it to.
So it's going to call it player.
And it's got the suffix gd which indicates that it is a GD script file.
Click create and that file will be opened and we will change our view over to the script main
screen.
Now, depending on the size of your screen, this may or may not be easy to see.
So I'm just going to quickly cover how you can make things more visible.
If you want to hide the tabs on the left and right, the scene tree, file system and Inspector, there
is this button in the top right of the main screen called distraction free mode, which will hide
those
side windows, and you'll see the main screen takes up the full width.
You do then need to remember that you need to either click that button again or push the
shortcut Ctrl
Another nice way to make the screen take up the full screen is to make this window floating.
If you click the button below that distraction free mode, there is a button to make this entire
main
window float, and you'll see it is now a window that I can move around.
It's worth noting that if you close this floating window, it will return to where it was.
If you change the main screen back to the script view, it will be back where it was.
I'm going to use this floating window so that I can focus entirely on the script we're dealing
with.
The first thing that is worth understanding a little bit is this very first line in the script which
That means because we attach the script to a node 3D, it has a 3D position.
That means that this script knows it has a position on the y axis, the x axis, and the z axis.
And there are a bunch of other built in properties that the script has access to.
The next thing we need to look at are these two functions that were added by default.
Functions are a list of instructions that get completed in order when the function is called.
I'm only going to focus on this first function ready to start with.
This function gets called the first time the node runs.
So when we first run our game, this ready function will be called and everything inside it will
be
When we added editor type hints as an editor setting, it added this extra bit of syntax.
This syntax says the data type that functions or variables are interacting with.
I'll get a bit more into what that means later on.
Understand how to follow instructions by making our game do something when it loads.
I'm going to replace this with a function that all scripts can call, which is print.
The print function will output some text that we provide to it in the output panel when the
game is
running.
You can tell something is a function because it is a name, followed immediately by an opening
and closing
parentheses.
Above is the word underscore ready, followed by an opening and closing parentheses.
So in order to print something out to the console while the game is running, we need to pass a
string
in.
So I will call its ready function, and its ready function will perform all of the code that is
within
the function.
If you hold shift and press tab, it will indent back into the left.
If I indent this function all of the way, you will see the line has gone red and there is an error
Essentially, after this function and the colon, it expects there to be something indented upper
level
And then everything that's at this indentation level immediately after this function is what will
be
I saved it by hitting Ctrl and S and now we can run the scene.
I will click the Play Current Scene button in the top right or use the F6 key.
As before, this scene has a grey view because we don't have a camera or a walled
environment, but
If we get rid of that window, we can see in the output tab in the bottom panel.
Here we can see a bunch of startup text and then hello world.
And the print function that said the words hello world was then called as well.
You can get to the script quickly by clicking the icon with the script attached to the player, or
by
I'm going to click the script icon and it will reopen that main window.
I want to make your game run and print out the following lines of text sequentially.
We already have.
Hello, world.
Don't panic.
Afterwards.
And then afterwards print the number 42, and I will see you back here in a moment for the
solution.
Returning to our game scene, we want to print those extra lines sequentially.
I am going to click the little script button next to our node in the scene tree to open the
associated
I'm going to close this and I'm going to click the Play Current scene button.
Close the window that opened and you will see our output panel is saying hello world.
The last thing we wanted to add was printing the number 42.
We type print again on a new line and then in double quotes the number 42.
Interestingly enough, we can actually delete these double quotes and print just the number on
its own.
And that's because the game engine treats numbers differently to text.
It's trying to read these words as either functions or variables, and it's getting very confused.
And because it's got punctuation and spaces, we need to surround it in double quotes for it to
know
that is one entire string I'm going to treat as one value I can access and use.
And we will see that it prints out Hello world, don't Panic and 42.
In the next lecture, we will be learning about the process function and start using inputs from
the
player.
Scripting Essentials
In this lecture, we are going to build on our scripting knowledge, learning about the process
function,
how to get input from the player and how to use variables.
So when we started we have this ready function that is currently printing three things out to the
console.
For a game to be responsive, it's going to have to update the screen many times every second.
These updates are called frames and your frame rate is going to depend on your machine.
So typically if you have a machine with better hardware, it will have a higher frame rate and
worse
hardware.
When you're using your machine, sometimes processes will run in the background.
That means we can be running a different amount of code in the same amount of time.
Because of this, we need the delta parameter as a way to keep our code consistent across
different
In this case, our process function is called and it is provided delta a value saying how long it
has
But given that, let's start seeing our game print something out every frame.
In this process function, I'm going to replace the pass keyword with a print statement.
Hello.
Now because this is printing every frame, it's going to very quickly become unmanageable.
And we can see our output in the bottom panel is full of hellos, and you can see on the right it's
So instead of printing hello I'm going to print Delta and run the scene.
Now you can see there the number was changing every so often.
And if I pause this there's a playback control on the top right where we can pause the running
project.
Now that output is going to stop continuing.
But this is going to let us dig through this output console in the bottom left.
So you're going to want to make sure you're viewing the output by clicking the output button
in the
And we can scroll all the way up to the top, because I saw something interesting which was
over the
first few frames, it printed what was in our ready function and then it printed the delta.
And the delta varied quite a lot because the game was setting up, so the frame rate was
varying.
With that understanding, I'm going to close and shut that off.
I want it to check if the player has pushed a key on their keyboard, and if they have, print
something
out.
An if statement starts with the word if and then it checks if a condition is true or false.
If the condition is true, it will do something, and if it isn't, it won't do that thing.
We can access whether the player is pushing a key through a singleton called input.
Not going to go into too much detail on it, but want to check if the player has pushed a key and
I
Dot is and you can see we have code completion for a bunch of the options we want.
Is action pressed.
And you can get that code completion by either using the arrow keys to go down and hit enter,
or just
click on it.
And then we want to check if the action that was pressed is accept.
And that's an action that's bound to pushing the space bar or the enter key.
We close off this if statement with a colon, which then separates out.
So afterwards, all of the indented lines of code will be run when the if statement evaluates to
true.
In short, this says if we have pushed the spacebar, do whatever is indented after the if
statement
so we can print something here I'm going to print spacebar was pressed.
And now if we run this code, whenever we press the spacebar, it should print out this line.
That's actually because I selected a slightly different input event to what I wanted.
What was happening there was while we were pushing the space bar down, there were
multiple frames where
the space bar was pressed, and on all of those frames it was printing out.
Just returns true the first time we've pushed the key down, and doesn't ignore the subsequent
frames
where we're still holding the key down.
I'm going to push space and it says spacebar was pressed whenever we do that.
I'm going to go into much more detail about using if statements and how you can use player
input in
subsequent lectures, but for the moment, this is a good starting point for us to just access that
information.
We can learn a bit about how we can actually handle these values we're printing out.
And when they take damage, take eight off of it, or take some number off of it and then store
what
In order to have these values that we store and interact with, we need to use variables.
So variables are a way of storing values, and we can store specific values in them.
So for example, if I were to declare a variable called my string and set its type to be string, I
could store some text like hello World, which is what we were passing into our print
statement.
If I have this Hello world value stored in a variable called my string, I could pass my string
into
a print statement and it would print out the value that was stored in this variable.
We can also store different things in variables.
And if we wanted to store something with a decimal decimal place we could use a float which
would be
something like 1.5 or 0.3 or whatever else, just something with a decimal place in the middle
of it.
And in fact, when we went to edit settings in the last lecture and we enabled type hints, that
was
Now, the reason you'd want to do that is when Godot knows what kind of data is in a variable,
it will
actually run a bit better because it can allocate its memory more effectively and other things
like
that.
So you will actually get better performance when you use strong typing.
It's also generally considered to be more readable if you're telling someone this variable I'm
dealing
with that stores the health is meant to be a number and not a word.
So given what we've just learned about variables, let's try and replace some of the stuff in our
ready
I'm going to add a new line afterwards and create my very first new variable.
I'm going to create var my number.
And now, if we try and print this, as I was saying, it will print out ten so I can print.
My number.
And when we run this scene we will see it's printing ten out here.
Now it is a variable.
But I'm going to show you how we can add one to it.
If after my number we add a plus and then we add one, what will happen is it will run that
operation
So what the print will receive is actually ten with one added onto it.
There we are.
This time I'm going to declare a variable outside of the function when we declare this variable
inside
This process function won't know that variable exists or be able to access it.
So if we want to create a variable that both of these functions can access, we want to define it
outside
And I'm going to call it a float, and I'm going to set it to be equal to 0.0.
What I'm going to do is I'm going to print out what timer is set to.
And if I run that at the moment, it should just keep printing zero.
But I'm also going to change what the value of timer is.
And now every frame that small number about 0.016 is going to get added onto what timer is
set to.
You will see this number is going to grow and keep a track of how many seconds it's been
since the application
started.
So with all of that knowledge, I have a challenge for you.
And that challenge is I want you to create a new variable that both the functions can access
that stores
an integer.
And whenever the spacebar is pressed, I want you to make that value bigger.
It doesn't matter.
It could be delta.
And then afterwards I want you to print the value of that new variable.
Welcome back.
So back in the script I am going to create a new variable to store this new number.
I'm going to declare a variable with the var keyword and I am going to store.
And then we want to start adding a number to it every time the spacebar is pressed.
At the moment, because we're printing something in the process function, that number that's
getting
printed out is actually going to get in the way of what we're trying to see be printed out.
And then with another value added on top, let's say add five.
So now every time we press the spacebar, we are going to add five onto the number that's
already stored
there.
If I run that.
Whenever we press the spacebar, it will say that we've pressed the spacebar and it will say the
value
The next time we push space, it will add five on top of that and we'll go up to 52 and so on
indefinitely
In the next lecture, we are going to put this theory into practice and start using our script to
make
the player.
So in order to have a player that we can see and interact with, we are going to need to give the
player
Now we can do that by clicking on the player in the scene tree, clicking control A to open the
Create
New node prompt, or clicking that plus button in the top left and searching for a mesh instance
3D.
If we go over to the inspector with it selected in the scene tree and we can see its mesh
property,
we can click the drop down to the right of that and we can select a new cylinder mesh I think
will be
And we will now default to having this about a metre tall mesh.
We now need to do the rest of the essential steps for making our 3D scene visible, and that is
adding
Now we can add that environment and directional light with those three dots at the top of the
viewport
And we can click Add Sun to scene and we can click Add Environment to scene.
And then in the create new node bar we will search for a camera 3D.
Click create to add this camera 3D to the scene, and you'll see it's currently inside of where our
player is.
So we're going to need to move it some distance back so that we can actually see the player
with the
Go down to the transform dropdown, expand that, and we will use its position property to
move it further
back.
I'm going to move it five meters back by setting the z value of the position property to five.
If we scroll the mouse wheel out, we will see it's five meters back and you can see the grid
showing
If we want to see how that looks we can click the preview button.
We can see the player's relatively small in the middle of our screen.
At the moment, if we start moving the player around with the camera here and that is the
camera is
That means when the player moves, the camera will move with it.
And you'll see the camera goes with it because the camera follows it around.
We actually won't be able to see that the player is moving up or down, because the relative
view is
going to be the same as the camera moves with the player.
I'm going to undo those changes to the players transform by expanding its transform property
and clicking
Thankfully, there is one little shortcut we can do to make it so that the camera won't move
with the
Normally, we'd have to create another scene and keep the camera parented to the root of that
scene
If we select the camera and in the inspector, go all the way down to the node 3D section.
Yes.
Now this is a really handy feature for making it so that a node will not move with its parent.
Say you have a gun that fires bullets and you want the bullets to not move.
When the gun moves, you can set the bullets to be top level, even though they're a child of the
gun,
And now when we move the player that camera should remain fixed in position.
Now we can move on over to the script, change over to the script tab, and I'm going to enter
distraction
We're not going to do anything in the ready function, and we're not going to use any of these
variables,
So one thing we can do to start with is we can start moving the player up when they push the
space bar.
So that's the how far they are on the x axis, how far they are on the y axis, and how far they are
on the z axis.
We represent a vector with the vector three object, and we can create a new vector using this,
which
is a constructor.
It creates a new vector three object.
The vector three has the first parameter giving its x value.
The second parameter giving its y value, and the third parameter giving its z value.
So this means this vector is roughly the same as saying it's a point in space two metres to the
right,
And in it it has an x value for how far to the left or right it is, how far up or down it is on the
So if we want to move the player up, what we can do is we can access their position, access
their
Y value, which is how high they are, and we can increase it or decrease it like that growing
number
With that in mind, what we want to do is when we push the spacebar, we want to move the
player up.
I'm going to say position and it will see it's auto completed that we have a position property.
If I hit Dot, we'll be able to see all of the functions and properties within that vector three,
which
I'm going to get its y value and I'm going to add a number to it.
I'm going to say position dot y equals position dot y plus two.
So now when we press the spacebar the player will move two meters up.
And if I run that hit the spacebar and they jump up and they keep going off.
So I'm going to make two changes to this to make it so that the motion is smooth.
So now every frame where we are pushing the spacebar a value will be added to position dot
y.
And then I'm going to do a very important step for making code like this.
That means every frame while we're holding the spacebar, the player is going to move up by
how many
That's nice enough, but this is a good opportunity for us to see some shorthand.
At the moment we're having to say position dot y twice, and this line of code is just a bit
longer
That's shorthand that says we're going to set position dot y to be equal to whatever it already
is.
Plus delta.
There are a bunch of similar functions like this for minus equals or multiply equals or divide
equals.
So you can see that this is fundamentally the same as saying position dot y equals position dot
y plus
delta.
So now we can move the player up when they push the space bar.
I'm going to use the left or right arrow keys because they're the easiest to access on a new line.
I'm going to say if input dot is action pressed, and I'm going to check if they've pressed UI
right.
I'm going to check if they've pressed left, so that's if they've pressed the left arrow key.
If they've done that, we want to rotate our shape anti-clockwise around the z axis.
And the way to do that, as simply as possibly is with the rotate z function.
You can see we've got a rotate X, rotate Y, and rotate z function.
We want to use the rotate z function and we want to pass in an amount.
Now the value that rotate Z takes is actually a unit called a radian.
All we need to know about this is that as we increase the number we're rotating Z by, it will
rotate
more counterclockwise.
For this challenge, I want you to rotate the player clockwise when they press the right action.
And that is you can rotate your shape positively or negatively around that z axis.
Okay.
So our starting position is we want to do something when they press the right action instead of
the
left action.
So on a new line I'm going to say if input dot is action pressed UI right.
And you can use this minus symbol in the same way we've been using the plus symbol
previously.
I can rotate left, and if I push the right arrow, I will rotate right.
In the next one, we are going to move on to blocking out our first 3D level using 3D shapes.
So our starting point should be figuring out how we want our level to look for Project Boost.
We have the ground, and we have a launch pad where our rocket is going to start the level, and
a landing
So the three core things we're going to want to lay out in this level scene are the box that is the
ground, the box that is the launch pad, and the box that is the landing pad.
So click the plus icon at the top of the viewport to create a new scene.
So the node we are going to use to construct our 3D geometry is a CSG box 3D.
CSG stands for Constructive Solid Geometry, and it's a very helpful prototyping tool that will
allow
you to create interesting shapes dynamically.
And then you can then export those meshes out into another piece of software, like blender, or
another
So we're going to want to add a new node to this scene with Ctrl A, and we're going to search
for CSG
box 3D.
Just by starting with CSG, you can see all of the options for different CSG shapes.
But we want a CSG box and you will see we have a one metre by one metre by one metre
cube.
Either with these little orange dots, you can click and drag them to resize, or we can use this
size
I am going to use the size property because I have a good idea of how big I want this level to
be.
So because it's eight meters tall, well, the dimensions are eight meters.
It spreads four meters out from the zero point that way, and it spreads four meters downwards.
So if we set its position to negative four, the top will line up with the middle.
So I'm going to go down to the transform property and set its positions y value to negative
four.
And now we have this big box that will act as the floor of our level.
I'm going to rename this box by double clicking on it, and I'm going to call it floor.
Later on, we're going to want our ship to be able to stand on the floor or crash into it.
If we click the dropdown to the right of a new material, you will see a few different objects we
can
choose from.
This has made it a little bit lighter, and it's going to let us choose a color for this mesh.
If we click the dropdown, this is an object that we can access in the inspector.
And it has a whole bunch of properties of its own that are distinct from the properties of this
box.
So if I click on this sphere in the viewport, it will expand.
And you can see it's got a blue border because this is all one object, but it has a whole host of
properties.
It's got things like transparency, metallic roughness, emission to make it glow, all of that stuff.
Now that means it's not too trivial to find where the color is.
So under the albedo dropdown you will find the color of the shape.
And if we click on this color property, we will get a color picker that lets us choose the color
for
We can get rid of all of the green and our shape will come even more blue.
So we have access to this color picker and you can select whichever color you want.
We of course have the red, green and blue channels, but we also have hue, saturation and
value.
So you can choose how saturated and how vibrant the colors are.
And also you can deal with the color on a scale of 0 to 1, rather than a value of 0 to 255.
It's worth noting that the CSG box, while it's selected, highlights in a bit of a blue tint, which
is going to make it hard to see these changes until we unselect the box.
And then I think I'm happy with that as a color for our floor.
So now we know how to make a box, we know how to resize it, and we know how to give it a
color so
I want you to make the launch pad, and I want you to make the landing pad.
They both will need to be renamed, so one of them should be called launchpad and the other
should be
I'll recommend making the launchpad a shade of blue and the landing pad a shade of green.
And with that, I will see you back here in a few moments.
And I'm going to add a new CSG box 3D by hitting control A to open the Create New Node
dialog.
And we can see something interesting to start with because it's spawned in the middle of our
world,
So if we want this to not clip into the floor, we're going to need to move this up at some point.
I'm going to move it a bit to the left, and I going to make this shape a bit wider.
Okay.
Its wider that way.
And now we can increase its depth by setting the z size to two meters.
I'm going to decrease its height on the y axis to something like 0.4.
So we need to lift it up less far to make it not slip through the floor.
And because it's 0.4m tall, if we move it 0.2m up, its bottom will touch where the floor is.
So I'm going to go down to its transform property, and I'm going to set the Y position to 0.2.
We're going to want to set its color to a blue shade of some description.
So under its material property we can click the drop down to the right and select New Standard
material.
And as before under the albedo property we can find the color property.
And in here we get a color picker where we can pick a blue sort of color.
Now if you want to see what these colors are immediately I think this is a bug.
But I think if you decrease the value on the right because it's starting at full brightness, you
can't
But if you decrease the value by dragging that slider down, you'll start to see what all the
colors
are.
So I'm going to select a sort of pale blue.
Done.
When you're moving around the viewport like this, you might want to move the camera to the
right or
to the left.
And then when you click your middle mouse button in and drag your mouse around, you will
pan the camera
So now if I drag my mouse to the left, I'll move the camera straight right, and I can look all the
way over to the other side of the screen, rather than having to fiddle around by rotating the
view.
I could copy this and edit it, but I'm going to show it from the ground up again just to reinforce
I'm going to hit select the root level and I'm going to add a new child.
And then I'm going to set its size to two meters on the x axis, two meters on the z axis, and the
height was 0.4 I think.
There we are.
I'm going to move it up to 0.2 so it's no longer clipping through the floor.
And then I'm going to give it a color by selecting the material and adding a new standard
material.
So I'm going to drag to a value that's a bit more readable and pick a sort of orangey red there.
And so I'm going to go into the hue, Saturation and Value tab within the Color Picker.
And now we can see we have a blue launch pad and a red landing pad.
And I've been very silly because I forgot it's supposed to be green.
So let's go ahead and change that over to a green color on Hue Saturation value.
I'm going to keep the same saturation of value, but change the hue over to a green.
And with that, we have something approaching a level we can get started with.
In the next lecture, we are going to get our rocket into the level and work a bit more on the
code
for moving that from the launching pad to the landing pad.
I'm actually going to start things off this time with a challenge, reinforcing something you've
done
And then add a camera 3D to the level and try and aim it so that you can see both the launch
pad and
I wanted to start off with this challenge, because knowing how to add a world environment in
a directional
light is very important whenever you're setting up a scene, as you might be able to see things
otherwise.
So if you look at the top of the viewport, there are the three vertical dots.
And in there we have our preview son and our preview environment.
And click the Add an Environment Scene button and the Add Son to Scene button.
And now when we run this level, it will have the preview environment we can see in the
viewport.
We select the root node, we hit control and a search for camera 3D, which clearly I've done
recently.
So making sure that camera can see these two points requires a little bit of fiddling with its
position
So I'm going to use the 3D gizmo and move it back until I think it can about see those two
points.
Now you can see we are looking straight on at the side of the stage.
So whilst still in this preview mode, I'm actually going to use the values in the inspector to
update
the transform properties so that I can see in real time how it looks.
So with the camera 3D selected, scroll down, expand the transform dropdown and in here I
want to move
I'm holding shift and dragging to have a bit more fine grained control.
So I'm going to hold shift and I'm going to drag down to decrease the x rotation minus.
And now I'm seeing I can see a little bit of the underside of the stage.
And now I'm noticing I can see the back corners, so I'm going to move it closer again.
So now when the game runs, we'll be able to see the landing pad on the left and the the launch
pad
There we go.
So I'm going to create a folder in the root directory in the top right I can click create folder and
Now we have an empty folder called level where we can keep all of these scenes and scripts
related to
our level.
And now the game will run and we can see those two points, although we can still see the back
corners.
So I'm actually going to move it a little bit closer because the viewport doesn't have exactly the
same
So.
Although actually now that I've relaunched it, it is perfectly showing me what it can see.
So let's just drag that until we can't see the corners of the level at least.
And we can see after saving that level in its own folder, we now have a level folder in the file
system
So the next thing we want to do, I'm going to exit that preview and collapse.
We can either right click on them in the file system and click instantiate.
And it will let us search for the player scene, which we can see there, or the level scene.
So instantiating effectively creates a copy of our player in another scene, and whenever we
edit our
original player scene, those changes will be reflected in any instantiated players in other
scenes.
And we now have the player, and the player has been positioned in the middle of our level.
We can also see that the player has got that camera attached to them.
And actually the player has a few nodes inside it that we do not want in this level scene.
So I'm going to save this and I'm going to open the player scene.
Now when you instantiate a scene in another scene, you can quite quickly get to them.
You can see I have this player scene, and it's got this little clipboard with an arrow to the right
of it.
If we click on that clipboard, it will open that player scene in the actual main viewport.
Now because our level has a world environment, a directional light and a camera, we don't
need any
of those in here.
And if we reopen the level, those changes will have already taken effect because this just loads
whatever
There's a nice, easy way we can recenter the player on the launch pad, and that's to do with
relative
transforms.
Because when you move a node, all its children move relative to it.
When I set the player as a child of another scene, its position will become relative to that
parent
node.
So the player, its transform at the moment says it's at position 000.
If I make it a child of the launch pad and now look at the player, the player is still at 000, but
That's because this global 000 position is 7.5 to the right of that launch pad and 0.2 down.
If I now reset this position, it will have its position set to 000, but locally to that launch pad.
I can reparent it to the level and it's going to stay where it was, but it's going to have its
position
I'm actually going to neaten that up a little bit and set it to exactly 1.4.
So when we push space, it should go up and when we push left, it should rotate left.
We push right.
It should rotate right.
Next time we are going to learn about rigid bodies and really improve the way the player script
runs.
So where we left off, we have our player in our scene, but it has a lot of aspects of it that are
It's only ever moving globally upwards, no matter how it's related.
For example, if it was angled like this, we'd want it to move that way.
But at the moment when we push up, it moves in the direction of the green arrow.
So in order to tackle that, we are going to need to introduce a new kind of node for handling
physics
operations.
And depending on what its mass is and the size of the force we apply, it will move in that
direction.
And if we want to rotate it, we apply a different kind of force called torque.
And those are the two key functions and two key forces we are going to use to control our
body.
So we want to take our body that is currently a node 3D and turn it into a rigid body.
Now we could just recreate the scene as a new one, but I want to keep what we've done and
show you
So I'm going to open the player scene and in here I'm going to select this root node.
And in the dropdown you will see an option called Change Type.
Change type lets us re select what kind of node this node is.
And you can see in the inspector on the right that the node is a rigid body.
The reason the symbol is still a bit confused is because we have a script attached to it.
I'm going to open that player script and in there you can see the top line says it extends a node
3D.
So currently this is a script that gives us all the functionality of a node 3D, but doesn't give us
I'm going to change that first line to say rigid body 3D.
And now this script will give us all of the properties of the rigid body 3D.
I'm going to save that scene, and I've noticed that the actual symbol for the player doesn't
update
until this scene is closed and reopened.
So I'm going to close that player and I'm going to well, you can already see in the level the
player
But if I reopen the player scene now, we can now see that this node is a rigid body 3D.
The error message is essentially saying that our body can't interact with the physics of Godot
until
It's a shape, but it's a shape that's only used internally for figuring out how an object is
colliding
I'm going to with the player selected in the root node, hit Ctrl A to open the Create New Node
dialog,
3D is what we want.
Going to select create and we now have a new collision shape node.
This collision shape node is saying that it currently doesn't have a shape set in its shape
property.
If we look over to the inspector, that collision shape can have a variety of shapes attached.
If we click the drop down to the right of shape, you'll see it could be a sphere, a box, a capsule,
a cylinder.
And then there are other interesting ones like world boundaries and height maps.
I'm going to select the same shape that our mesh has, which is a cylinder, and you can see if I
make
We have this cylinder here that is exclusively used by the physics engine for checking whether
this
So when the bottom of this is resting on the floor, our rigid body will stop falling through the
floor
at that point.
With this rigid body, there are a few properties we want to update.
For a start, when we're moving our player, they're going to only be moving up and rotating
around
So we don't want them to rotate along any other axes, and we don't want them to move in or
out of the
screen.
And in axis lock I'm going to limit a bunch of the motion and rotations that can be applied to
this
rigid body.
I'm going to lock linear z movement so it can no longer move on the z axis.
Damping lets us slow the motion over time and we'll just make the movement a bit more
sluggish, which
may not sound appealing, but actually, when using a physics simulated body, having damping
really
I'm going to bump the linear damping up to one, and I'm actually going to bump the angular
damping
up to three.
That's going to mean the rotation is a lot, is much more damped than the movement is, but it's
going
to mean that the shape loses its rotational velocity a lot quicker.
With all of those properties set up, we can start to look at the actual controls for this rigid
body.
I'm going to open that player script and make it take up the full screen.
And we're no longer going to be controlling it by accessing its position dot y and increasing it,
or
And that's going to apply a force that will move the shape in a direction of our choice.
Now when you have a vector three, we could define it as by passing in the values of the x, the
y and
the z axis.
But actually there are a bunch of predefined vector threes that we can use as shortcuts.
You hold Ctrl and click on the up part of vector three point up.
And you can see that these are a bunch of constant vectors with set values.
So vector up here is exactly the same as declaring a vector three with zero on its x value, one
on
I'm going to click the back arrow in the top right to go back to the documentation.
You can alternatively click on the player dot file name in the top left here to go back to the
player
script.
I'm going to multiply that by delta because we want to make it frame rate independent it.
And lastly, we're going to want to choose the magnitude of the force.
So you can essentially split a vector three into two parts a direction, what way the vector is
moving
Imagine aiming throwing a ball in a direction, and the magnitude is how far you're going to
throw it
At the moment our shape is quite heavy and the value of delta is quite low.
And that's going to apply a large enough force that we will see the shape start to move if we
play.
And now when I push space, a force is applied and gravity pulls it back down because it is a
rigid
We are currently rotating on the z axis because we're rotating around the z axis.
We want to apply torque around our z axis, so I'm going to apply torque.
I want to pass 0.0 into the x axis, 0.0 into the y axis, and then an amount of torque into the z
axis.
I'm going to pass in 100 because as before, we need quite a large number because we're about
to multiply
it by delta.
So now when we push the left arrow key, torque is going to rotate our shape.
Given that we've just applied torque to make our shape rotate left, I want you to do the same
thing
You still have all of the boilerplate code for rotating on the z axis using UI, right?
Which should lead you in the right direction to figuring out how to use torque to rotate
clockwise.
Welcome back.
So we want to apply torque to rotate clockwise when we press the right key.
I'm going to copy everything we said for left, because we're going to be doing a very similar
action
in the same way, rotate Z controlled, whether it was clockwise or counterclockwise, using
whether
the value is positive or negative, we can change whether our torque is positive or negative to
control
So I used control C and control V to copy and paste that apply torque function in.
And then I'm going to add a negative symbol before the 100 in the apply torque function, to
make it
So we know we have a global upwards direction stored in vector three point arc.
But if we want to find out what direction is locally upwards, we need to access a rotation that
is
known as a basis.
So our character stores what way it thinks up, left, right, forward and back is in a object called
a basis.
And we can get whatever direction is locally upwards in the Y property of that basis, that Y
property
And it's also got a z value pointing locally forwards and an x value pointing locally to the side.
So we're going to want to use this basis y value instead of vector three point up to move
locally up
Then we just want to take vector three up and we want to swap it out with basis dot y.
And now that is giving us a local up direction that we're multiplying by delta and then by
1000.
I pushed space.
It'll go up.
If I rotate right and push space, it'll start going to the right because up is a value slightly to
the right.
If I push left, it will start going to the left because up is slightly to the left and depending on
how steep that is, the amount it moves will be greater or lesser.
And now we have a physics simulated rocket ship that we can control and make land on our
landing platform.
In the next lecture, we are going to look in more detail at binding inputs, so we can start using
more convenient keys than the left and right arrow keys.
So at the moment we are controlling whether the player moves using these built in input events
UI except
These are built in actions designed to help the user navigate user interfaces.
We want to define our own, and we want to choose what keys will control that action.
And this is a very powerful system because it lets you do things like have a key on a keyboard,
control
an action, and have a different key, well, a different button on a controller trigger the same
action.
So with that all said, let's dive into the input map.
If you go and look in the top bar, look at the menu buttons, click project, and in the drop down
If you click on the input map, this is where we can define a new actions and choose what keys
control
At the moment this is empty, but UI left, UI right and UI accept are in here.
They're just hidden.
We can click this toggle in the top right to show built in actions, and you will see all of the
actions
that are built in so that UI accept action we were using to make the spaceship fly upwards was
controlled
by pressing enter or space on the keyboard, and UI left is pressing the left key or pressing left
on
And we can add a new action by clicking on this text box at the top that says add new Action,
and we
That is, when we move upwards that's going to be controlled by something like the spacebar.
And then I'm going to click the add button to the right of that.
And now the boost action has been added to our input map.
Now we want to attach key presses to this boost action that will trigger it to the right of it.
And this bin icon bin will get rid of the action.
So I've pushed the space key and you can see it's selected space physical as the top.
And now you can see boost is triggered by the space physical key press.
Because typically your control movement with W, A, S and D and PC gamers tend to associate
W with
moving forwards.
And this time I will push the W key and it's detected the W physical key press and I can click
okay.
For example, you can make the event only trigger when the user is holding alt and pressing
that key,
or holding shift and pressing that key or any of the other typical modifiers.
Instead of using UI, except use the boost input event action.
Now because that event is in our input map, we are going to get code completion here.
If I hold control and hit space while is action pressed is empty, it will open code completion
for
And because boost is the only action we've defined, that's right at the top of this list above all
When we push the boost key it will apply our force upwards.
And if I run.
I can hold W and it'll move up, which it did not do before.
I want you to add one called Rotate Left that is bound to the A key and the left arrow key.
And then afterwards I want you to update the player script to use those two new actions
instead of left
and right.
Okay.
Welcome back.
So back in project Project settings input map we want to define a new action, one of them
being rotate
left.
So in the Add new action text bar at the top I'm going to type rotate left.
I'm going to add the A key by pressing A in event configuration and clicking okay.
And this time I'm going to press the left arrow key and click okay.
Rotate right.
I'm going to hit enter this time because that does the same as hitting the add key there, the add
button
there.
And I'm going to click the right arrow key and click okay.
I can close this and I can replace UI left and UI right with rotate left and rotate right.
I'm going to select the UI part, get rid of it and type rotate in and we've got rotate left and
right.
You can actually see the code completion is already trying to offer us the two available input
events
from that input map.
But I've typed it out there and for this one we want rotate and this time rotate, right.
And with that done, when I run the scene, I should be able to control it with the A and D key.
And that's how you add inputs and select what keys control them.
It's a very powerful system and really well worth knowing the ins and outs of.
In the next lecture, we are going to start detecting collisions to find out when our player has
landed
Collision Detection
In this lecture, we are going to learn how to detect when a player touches the landing pad.
So there are a whole host of different ways to detect when one object starts colliding with
another.
And in order to understand that, we need to know a little bit more about signals.
So signals are the main tool for letting game objects communicate with each other.
Objects like nodes, but not limited to nodes, can emit signals in code.
You can connect a signal to any number of functions provided the parameters match.
So for example, if I have a signal that is trying to send an alert out with a string parameter, the
method I connect it to has to at least accept that string parameter, or there will be an error.
And I'm going to show you how to connect signals from the rigidbody 3D in the editor to
code.
So our first step, I'm going to exit distraction free mode and go into our player scene.
Change the 3D mode so we can see we're dealing with just our player.
We want to edit this player scene, because if we edit the player that's in the level, it will only
And we want this to affect any player we instance in any other scene.
So we can access the signals that a node has through a tab next to the inspector, I'm going to
select
And over in the inspector on the right I'm going to click the node tab at the top.
Firstly we get signal options and just next to that we have group options.
And you can see we have signals that come from the rigidbody 3D and from the various nodes
that rigidbody
3D inherits.
We want to detect when another node or another body like the landing pad touches our player.
Whenever this body touches another body, that signal will fire and tell us in code what body
has touched
this one.
And I'm going to click the connect button in the bottom right.
What it's going to do at the moment is it's going to take this body entered signal from this rigid
body
It's just going to create a new method in that script that the signal connects to.
So with all the default settings, we can just click the connect button in the bottom left.
And in here we can see we have a new function called on Body Entered.
The first thing I'm going to do just for debugging purposes is print the name of the body we
landed
on.
Dot name.
Because we've set the names of all of the physics objects in our scene, we should see that print
a
There's one more step we need to go through for this to work, and that's related to us using a
rigid
It's not typical for you to want to check collisions for all rigid bodies in this way, because you
You don't want them all to detect whenever they touch with each other, typically.
So exit full screen mode and I'm going to select that root node and go back in the inspector to
the
inspector tab.
And this is the property that says the rigidbody will emit signals when it collides.
Now the thing is it limits how many contacts it will send signals about.
This just lets you be more performance conscious when you're handling rigid bodies that
might have an
awful lot of collisions, but because we only care about this one player, I'm actually willing to
have
And we did that with the max contacts reported property that if I hover over it here, you can
see the
tooltip for.
And that means in a frame up to ten collisions with this body will be reported.
So let's do that.
To make life a bit easier, I am going to run the scene and I'm going to select a default scene
because
at the moment I don't want to run the player scene, I want to run the level scene and will
typically
So I'm going to click the select box from that selected default scene page, and I'm going to
open the
level directory.
And I'm going to select Level Scene as the default scene for our game.
I'm going to move it up a bit so that we can see our our output panel.
And you can see it's already said all I've I've touched the launch pad.
And if I fly up a bit and go down again, it should say there we go.
So what I want to check is what it says on the ground and what it says on the landing pad,
which should
And we have the landing pad many times and then the floor because we fell over.
But perfect.
So we could now use something like an if statement to say if we've touched the landing pad,
win the
game.
From there I'm going to hit Ctrl C after selecting landing pad so that I don't accidentally
mistype
Here we need to turn body dot name being equal to landing pad to be either a true or false
value.
This just turns these two objects into that either true or false value, giving us true.
If body dot name is the same as landing pad, and false if it isn't letting us use it in this if
statement.
So now with that done, I should be able to fly the ship again, and this time it will only print out
You win.
Even if it's not supported in code, we at least can test out as though we actually win the game
here.
So let's land.
And we win.
Perfect.
If we ever change the name of landing pad, this little check here will stop working.
In order to get around using this magic string, we can instead opt to use a slightly different
kind
of check to check if that body is the landing pad, and that's going to be using groups.
And the convenient thing about groups is we set groups in a very similar place to where we set
signals
going to exit full screen mode, close the output panel, and I'm going to go to the player.
Uh, or when you've got it selected in the scene tree, you can hit F and it will center your view
on
that object.
So with this landing pad selected, I want to add a little tag onto this landing pad saying this is
So with it selected in the inspector on the right, click the node tab again.
But to the right of this blue signals button there is a button that isn't selected called groups.
And if we click on that we will get option to add groups to this node.
What we can do is we can add a string in here and it's effectively attached to that body.
We can do a lot of things with groups.
We can check if a body has a group, or we can go ahead and get all of the nodes that have a
specific
group in a scene.
They're very flexible and useful, but I'm going to add goal as the group onto our landing pad.
And then going to copy that, because this does still use string references, but it's a bit easier
to refactor.
So I'm going to dip over back to our player and I'm going to go full screen again.
And now instead of checking off our body name is equal to landing pad.
Get groups.
We could add another goal, another label to it saying it's green, or that it's a target or that it's
movable.
And so because of that, we need to check if this string is in the list of groups, that is the groups
Anyway.
Now when we touch the landing pad, it will use the groups of the body to check if we've won
instead
of the name of the body that we're much more likely to change.
And then I want you to detect that group in the players on body entered function.
And then you should print something unique to the output panel.
Okay.
Welcome back.
There we go.
But if you can't find it in the inspector, change it over to the node tab.
The reason I'm calling it a hazard is I'm at some point going to make it so that when the player
touches
something that isn't the landing pad, they'll crash.
I'm going to copy that and I'm going to return to the player script.
And now I just want to copy what I did here, but this time for hazard instead.
If hazard is embodied.
Bodykit groups.
And then I'm going to print something unique was the last part.
You crashed.
And I'm going to fly and I'm going to touch the floor.
There we are.
And with that, we've learned how to add collisions to our game and how to use signals and
groups at
In the next lecture, we are going to start improving our code by learning all about the export
annotation.
Words like if and func and var that are all reserved words within the engine.
There's an extra set of these reserved words that are known as annotations, and they begin with
the
They are things like at export Onready, RPC, warning, ignore, and there are a few others.
They're all grouped together so that we can reduce the number of reserved words that are in
the engine
and improve code completion when we're trying to use those annotations.
The annotation we're going to start with is the export annotation, which is really useful for
making
So at the moment, in something like our process function, we are applying a bunch of forces
that are
And magic numbers are numbers that we've hardcoded into our functions that someone
reading it doesn't
But someone reading this wouldn't necessarily know what that 1000 means.
And the way we'd do something like that is by at the top of our script, declaring a new variable
of
the type.
So I'm going to create a variable called thrust.
Now we can go to our function and we can replace that variable with thrust.
Now this is nice and we know if we want to change the amount of thrust we've got, we can go
to where
We can open this script and we can change this value here.
But if we want to make things less code centric and a bit easier to edit in the editor, we need to
export the variable, and exporting a variable makes it available in the inspector.
I'm going to do that right now by just before this variable keyword adding the at export
annotation.
And you can see it's doing code completion for a bunch of different kinds of export.
What we want to do is we want to save this, and we want to change over, to have our panels
visible
And select the player and go over to the Inspector view and you will see at the top of the
inspector
And I think we can drag it from side to side to increase or decrease it.
There's I'm going to click the three dots in the top right of the inspector and select Make
Floating.
And now it's a window that can move around independently of my screen.
The reason I've done that is I want to be able to use this next to the running game window in a
second.
I'm going to have that inspector panel open, and I'm going to have this game panel open.
At the moment when I push the spacebar, I have 1000 newtons of thrust being applied
vertically every
frame.
So 250 less.
And if I increase this to something like 2500 it'll be really, really fast.
There we go.
There we are.
So this lets us test new values much quicker than, say, going back in and updating the value in
code.
So someone hovering over it, you see in that tooltip it says no description.
So I'm going to close this and I'm going to close that floating window.
So this resets back to its original position and open this script.
You can see before the process function we have this line here that says process is called every
frame
That's a comment.
You can create a comment by typing hash, or you can turn any line into a comment by hitting
control
It doesn't execute like code, so it lets us write things about our code without affecting any
code.
So now this will set the description when you hover over it in the inspector.
When moving.
I'm going to exit distraction free mode, and I'm going to try and hover over that property.
And now you can see it says how much vertical force to apply when moving.
Swirly arrows pointing out when you type at export there is a bunch of code completion, and
that's
You could export a file or an enum, or you can set categories in the inspector.
There's lots of different things you'll want to export, and you'll want what you are exporting to
change
what that inspector shows up as the available options, so we can set an upper and lower limit
for our
Annotation.
So if I go back here, I go to the end of our export and I type underscore range.
You'll see.
So just like when we have any of these functions with parameter passing delta into process or
passing
a force into apply torque, we can pass some values into this.
And the first value we pass in is going to be a lower boundary for the range.
And the second value we pass in is going to be an upper boundary for the range.
So I'm going to set my minimum boundary to be 750 because that was quite slow.
And I'm going to set my upper boundary to be 3000 which is really big.
We have a slider and we can slide all the way from our minimum value of 750, all the way to
our maximum
value of 3000.
So we've exported our range for our thrust, but we still have two more magic numbers in our
torque
And then I want you to replace the 100.0 magic numbers in the applied torque functions with
this new
exported variable.
So the two values we want to change are the 100.0 here and the 100.0 here.
We are going to create a new value that's exported and just replace those numbers outright.
And I'm going to set it to be a float, and I'm going to set its default to be 100.0.
I'm going to Ctrl C to copy it and I can paste it in these two slots.
So I'm going to hit Ctrl and V with the 100.0 selected there.
We don't want to lose that negative sign, but we do want to replace the 100.0.
So now when we rotate left we will have our torque thrust value applied.
And when we apply the negative one and rotate right it will go clockwise.
Hit save.
We can see our torque thrust values visible here just below the thrust, and doesn't have the
slider
because we didn't set a range yet because we don't know what the upper or lower bounds
should be.
I'm going to click these three dots in the top right of the inspector and select Make Floating so
that
It's worth noting if your screen is big enough or if you're running on another monitor.
I'm going to set it to be much bigger and we should see just how much torque is applied now.
But it means we can customize that value and we can test out new values of talk as we go.
And now this is a really essential skill to learn, because whenever we're creating these scenes,
like
Because when we instantiate those scenes, the scenes where they're instantiated might want to
customize
those values.
And we're going to see at the moment we have set this scene to have a thrust of 750 and 1000
respectively.
I'm going to set those back to their defaults, because actually 750 was a bit low.
Actually for testing, I am going to up the torque to 200, because I'm going to show you that if
we
So this has an instance of player over here, and in here it's got torque set to 200.
It may be on one level I want the ship to have a higher thrust or I want it to have lower torque
if
I change it here, if I make this ship in the level, have 2000 thrust and save it, if I go back to
the player, it won't have overwritten these values.
It's only that instance that has the new exported values.
And that's one of the main reasons why exporting a value like this is so helpful, because it
means
we can have different places, have different values for the same variable.
In the next lecture we are going to be making new obstacles for the player to collide with and
actually
making the player get reset to the start of the level when they crash.
So presently in our collision detection, we check if the body we collide with has a goal group,
and
You win.
I'm going to create new functions that handle what we should do, all the different steps that we
should
So we can define a new function in the same way that these process functions and on body
entered functions
I'm going to start the definition with func, and then we need to pick a name for our function.
And now we have our optional typing where we can say what this function returns to the place
that it
was called.
And the way we tell it that is by putting a hyphen and the greater than symbol, and then typing
out
After that we put a colon, and then when we hit enter we'll be indented and everything on
these indented
I'm going to make this print something slightly different so that we can see it in action.
Kaboom!
And now we want to replace our hazard detections print function with this new crash sequence
function.
So the place where we've found out okay the body we've touched is a hazard.
Instead of doing this print here I'm instead going to call this function.
And that means we can just have lots and lots of things happen as part of that crash sequence
being
started.
And now whenever our script gets to this point, it will jump down and start running everything
in here.
Kaboom.
One thing that was interesting there is our player still had a very high thrust, and that's because
I didn't reset any of the properties I fiddled with in the last lecture.
I'm going to select the root node and I'm going to reset torque thrust.
Now in order to find out how to do new and interesting things with the level itself, I'm going
to need
We can call it anywhere and it will give us access to the scene tree in code.
And the scene tree actually contains a bit more than what we see in the top left when we're
fiddling
The same tree that we access when the game is running contains whatever our running scene
is.
The viewport when we launch the game, and it's what's in charge of our game.
Using this sentry object, we can change, restart and quit levels.
So, returning to this crash sequence after we print kaboom, I am going to get access to the tree
and
You can see the code completion was showing up there for gentry at the top.
It's this function here, and it gives us access to a whole load of extra functions.
Quit.
Reload.
Current scene.
Reload.
Current scene is actually the function I want to call, and what that does is it unloads whatever
the
So now whenever our player crashes into a hazard, our scene will stop and reload and the
player will
respawn back where they started because the whole scene has reloaded.
The player should move at a normal velocity, and if I touch the floor, it should reload the
scene
That's how we reload the current scene and we can move on to our challenge.
So I want you to create another function similar to the crash sequence function I just added.
And I want you to call that function when the player touches the landing pad.
Just like get treat reload current scene, I want you to call the get treat quit function when they
Okay.
Welcome back.
We want to define a new function just in the same way as we did with crash sequence.
Go down to the end of the script and I'm going to define a new function.
It takes no parameters.
So I'm going to the hyphen the greater than arrow and type in void.
In here.
That wasn't part of the challenge, but I'm just going to replace the existing print and we want
to
call the get quit function exactly the same way as here.
Don't and then quit all one word and you can see that function showing up here.
And what that function does is it will exit our game completely the same as us clicking the
stop button
So now.
I also need to call this function when we are in our on body entered function.
If the body we've touched as the group goal, we want to call the complete level function.
There's one extra thing that I think's helpful to know about when it comes to understanding the
scene
tree, and that's knowing about the remote view when the game is running.
And you will see that on the left in the scene tree there are these two tabs.
Now local is showing us the scene tree for this level scene but remote.
If I click on that and reopen, this actually shows us our scene tree as it's running.
In fact, I'm going to make this floating so that I can see them side by side.
There we go.
So if I click on this route, this is what we're getting access to when we're accessing the scene
tree.
You can see it's got a bunch of information about our window in the inspector.
And it's what holds all the functions like reload, current scene and all the rest of that stuff.
And when our game's actually running, our level gets instantiated as a child of that root node.
And when we do this scene gets instantiated and a new one gets instantiated to replace it.
This can also be very helpful for debugging our level in real time, because we can do
something like
click on the level and expand it and look at whatever the current position of the player is
separate
from the position of the player and the level that won't have updated.
All right.
And with that done, you should know a bit more about creating your own function calls and
using some
In the next lecture, we are going to be progressing onto new levels when our player character
touches
subsequent levels.
In this lecture we are going to learn how to export file paths, which means we can have our
landing
pad store the path to the next level we want to load when the player touches it, and then that
will
set us up to make any number of levels going forwards, pointing our landing pad to whatever
the next
So let's select our landing pad and let's right click on it and click Attach Script.
And this will create our script called Landing Pad, the same name as the node we're attaching
it to.
And it's putting it within the level directory because that is where this level scene is.
Now we have that new script and we're going to want to export a value.
Now this is going to use the export file annotation which is a little bit different to exporting a
float,
but similar to when we exported a range to define upper and lower boundaries for our float.
So I'm going to start with at export and we're going to get some code completion.
Because we can pass a parameter into this to restrict the number of valid files we can look at.
But I'll show you why we want to do that by not using it first.
And we're going to give it a name I'm going to call it File Path.
We can exit distraction free mode, select the landing pad in the scene tree, and you can see
we've
The problem we have at the moment is we can select literally any file.
We can select SVG files, get related files, our file.
But we only want to be able to select scene files like our level.
So I'm going to go back and I'm going to show you how we can do that.
Within these parentheses for the export file annotation, we can pass in a string telling the
annotation
And that will make sense in a second when I follow it with Dot TSN.
So this is saying it will only let us select files if they have any characters at all.
So they can have absolutely any name, but they have to end with the suffix TSN.
So now.
If I accept distraction free mode, select that landing pad again and click the open a file prompt.
This will behave a little peculiarly, but it will work for us for the moment.
At the moment this means we have a reference to this scene attached to the landing pad.
So when we go and land on the landing pad, we can try and load that level, which will do the
same
But later on when we make new levels, we'll be able to point that path to a new level.
And in exactly the same way as get reload current scene and get dot quit.
This will use the tree because that manages our scenes.
So in our player script going to full screen that we want to make changes in our complete level
function.
So at the moment when we use complete level it calls get tree dot quit.
We want to change the scene and we want to change the scene to the file that is stored in the
landing
So we want to change.
We want change scene to file because that uses a file path to load a new level.
I'm going to say I'm going to call this variable next level file.
I'm going to put that in the open brackets here in the same way as process takes delta in and on
body
This function is going to take a variable called next level file in which is going to be a file
path.
So now whenever we use this complete level function, it expects us to provide a string as well,
telling
us what level we want to load.
And then all of this code inside will run, printing out level complete, and then changing our
scene
It's having an error because it doesn't like us not passing in the file path.
So now in here we know we have touched the landing pad because it has this goal group.
So it has all the member functions and variables that that landing pad does.
If we add a goal group to a body that doesn't have that file path variable that our landing pad
does,
this will throw an error, which is something we can make more resilient code to guard around
later
So as it stands, when we touch the landing pad, it should reload the current level using this
change
I am going to.
Lie.
A little bit ineffectually, but I did make it.
And then let's touch the landing pad and our scene reloaded.
And that was using the path to this level that was saved within the landing pad.
This means we can now make new levels, and we can change the landing pads file path to
point to the
I'm going to create a new very similar scene called level two.
And the way I'm going to do that is by duplicating this level I'm going to right click on it.
So we want to add something in here that will make us able to see a difference when we load
the new
level.
I'm going to select the obstacle and under the material property, I'm going to add a new
material to
So I'm going to click drop down to the right of material and click New Standard Material.
The reason I'm not editing the one that's in here is because the resource will be shared between
these
two objects.
So if we currently change this brown color to something else, the floors brown color will
change as
So I'll go down to the albedo dropdown and under color I will use the color picker to select a
color
of my choice.
I'm going to do a sort of magenta color, but a little bit softer and maybe a little bit paler.
You know, we now have a pink obstacle in the way that we need to get over.
And because this obstacle has the same group as the floor, it has the group hazard.
We need to hook the landing pad in level one to redirect us to that level two we've now
created.
So I'm going to click on go into level one, select the landing pad and in the file path exported
property
So now when we touch that landing pad, we'll get the path to level two.
Level two and our game will change over to here and now when we touch the ending landing
pad, because
When we touch the end, it will go back to the start and we'll be able to replay these two levels.
Perfect.
Let's see.
Perfect.
For this challenge, I want you to create another level called level three scene.
I want you to resize and reposition the hazard to make this level visually distinct.
And I want you to update the exported variable at the end of level two, attached to the landing
pad
And with that, I will see you back here in a few moments.
Welcome back.
So we want to make level three, and we can do that in exactly the same way we made level
two.
I'm going to move the box above the player and I'm going to make it much wider.
So now if we want to make it to the end, we have to fly below this, which is going to be a bit
harder
I think.
The last step we need to hook this up is to make the landing pad at the end of level 2.2, level
three.
I'm going to set the file path to be set to level three point scene.
Let's try and get over this one and hopefully be able to make it onto level three.
Perfect.
Of course I am.
Like a glove.
And with that, you now know how to export file paths and change scenes to new levels.
And with this, you can create absolutely any number of levels by varying the hazards we have
to get
past.
In the next lecture, we are going to start tackling using the tween node to animate changes.
Introduction Tweens
In this lecture, we will start learning how to use tweens to sequence events in code.
Its name comes from the animation term for inbetweening, where you would create a point in
between
Tweens are ideal for simple animations, and you can use them to do a whole bunch of things,
including
animating properties.
So, for example, changing scale over time or changing the position of a node.
They can also call functions and you can make them wait a certain amount of time.
In order to use a tween, we need to create it in code, and then we need to give it a series of
instructions
to perform.
So the case we're going to start with for this lecture is we're going to create a tween with the
create
tween function.
And then we're going to use the tween interval function to make it wait for one second.
After that, we can make the tween call our function that reloads the current scene.
So for example, when we crash our ship, this will make it so that instead of immediately
reloading
the scene on a crash, we will get one second to view the ship ragdolling before we actually
reload
Usually we would have an open and closing brackets after reload current scene, and that would
call
We're telling the tween the name of this reload current scene function so that it can call that
function.
So that's why there aren't opening and closing brackets on the end.
So let's jump over to our script view and a distraction free mode and jump down to our crash
sequence.
So at the moment we call our crash sequence print kaboom and then reload the current scene
just above
it.
And then afterwards we want to call the tween interval function to wait a set amount of time.
We passed in ten.
Half a second.
So do 1.0.
And that's that interesting syntax I was talking about of having the name of a function without
brackets
after it.
So we can pass in this part of the function as the callable without the brackets.
We will wait one second and then the scene will reload.
It said kaboom.
If I touch the floor and then start holding space again, I'll keep flying.
It would be really nice if the moment we touched the floor, we lost control of our player.
And I want to point out that all of our movement and force is being applied is occurring within
this
process function.
Now, there are many cases when you might not want a process function to run, and in order to
account
for that, there is a built in function that lets us disable this function as a whole, so it will no
And if we disable it, we will no longer be applying forces when we're holding down keys, and
it will
And the way we control that is with the set process function.
So I'm going to go down to the crash sequence just after we print kaboom.
And we can see process takes in a value called enabled, which is a bool.
So we're either setting process to be true, in which case we are processing or we're setting it to
I am no longer applying forces, as you can see there, it just fell over.
You'll notice that I've only crashed a couple of times, but it said kaboom many more times and
that's
Sometimes there we've crashed into the floor and we've started crash sequence.
And then as say, the top half of the body falls over and touches the floor.
A different part of the body starts the crash sequence and it will print kaboom a second time,
and
this other tween will start running, attempting to reload the scene.
Afterwards, it would be much nicer if we only called crash Sequence once, and then once
we've done
that, stop calling any more of the complete level or crash sequence functions.
And the way we're going to do that is with our own special boolean.
And at the top I'm going to declare a new variable just below these exported ones I'm going to
create
So colon bool.
So that can be for either crashing or for changing the scene I'm going to use whether or not we
are
transitioning to determine whether or not we should call another one of the functions that starts
a
transition.
And in here, if we are transitioning, we don't want to call any of these functions.
Is false.
I'm going to put a colon and I'm going to select these lines of code.
So now we want it so that when we start crash sequence or when we start complete level, we
set is transitioning
to be true.
So in crash sequence, because that's the one we're handling at the moment just after set
process.
False.
I'm going to call I'm going to update the value of is transitioning and set it to be true.
So now whenever we crash, we stop processing and we notify our script that we are
transitioning and
Now we only get one kaboom when we touch the floor and fall over.
Here we go.
Just one.
Perfect.
So I want you to use a tween to add a one second delay to the complete level function in
exactly the
Now, in order to do this, I'm going to need to give you the callback function that you're going
to
call at the end of it, because reloading the current scene was easy enough, but we need to use a
bit
The last step of your tween is going to be adding a tween callback, and it's going to call get
treat,
But afterwards we need to tell this function the string name of the file it wants to load.
And in order to pass that into a value without using brackets that would call the function, we
need
to use this bind function at the end and then pass the next level file in.
So just make sure that you've got these lines, just as I've put here at the end of your tween after
And with that, I will see you back here in a few moments.
Welcome back.
I am going to close the bottom panel, and we want to do exactly the same as we were in the
crash sequence,
So we've created a new tween that we're going to give some instructions to.
And then lastly we want to do that last function call I did, which will let the tween call this
function.
And the way it did that was it called tween dot tween callback.
Now in order to get onto a new line and indented so that this just isn't one really long line of
code,
Now you'll see it's put the closing bracket on a new line and it's indented us within this
function
call.
Get tree.
So change scene to file getting rid of those curly parentheses at the end.
And then we want to bind this next level file parameter to it.
And with that, we are now delaying our change of level by one second.
So if I run this.
And I land on the landing pad rather than the hazardous floor.
There we go.
The last thing we want to do to finish off our complete level function is we want to change the
value
And we're going to do that in exactly the same way as crash sequence.
And then after we print level complete I'm going to do exactly the same thing.
And with that all said and done, we will now lock our inputs when we land on the landing pad.
Whilst we start our transition to the next scene and we won't be able to trigger any new on
body entered
function calls.
So that's all nice.
One of the big benefits of having an extra second delay like this is we can add animations or
particles
or sounds later on, and let the user actually see them before just making a hard jump cut to the
next
scene.
And with that all said and done, in the next lecture we are going to be improving our tween
knowledge
and we are going to be using tweens to start animating some of these obstacles.
Tweening Hazards
In this lecture, we are going to be building on our tween knowledge and start using tweens to
animate
So we're going to want to jump into a new level so we can start adding these animatable
hazards in.
I'm going to do that by going down to the file system, right clicking on level three and
selecting
And then I'm going to open that new level four scene.
Instead, we're going to be creating an entirely new obstacle, and that's going to be using a node
I'm going to select the root node, and I'm going to hit control A, and in the Create New Node
dialog,
It's shown up down here, and you can see a little description at the bottom saying that this is a
3D
physics body that can't be moved by external forces, and when moved manually, it affects
other bodies
in its path.
So I'm going to add this body to our scene, and we're going to want to add a mesh instance and
a collision
shape in exactly the same way as with our player rigid body.
We needed to add a mesh instance so we could see it and a collision shape so it could interact
with
And then I'm going to add a mesh instance 3D as a child of that moving hazard.
So I'm going to select that and century over in the mesh property in the inspector I'm going to
select
And I'm going to get access to its size properties to make it a three meter by three meter cube.
At the moment, I'm just going to move it a little bit higher so it doesn't do that anymore.
About here is fine, and I'm going to do a little shortcut to create the collision shape.
collision shape.
If you select the mesh instance 3D and the scene tree at the top of the viewport, you'll see this
contextual
We click on that, we will get access to a whole bunch of additional options and including what
I've
That button will create a collision shape with the same dimensions as this box, and it's going to
be
simplified.
You can also do things like create an outline, or there are a few other things you can create
from
here.
And now if I scroll down, you can see we have a collision shape.
If I make the mesh instance invisible, you can see we have a collision shape with exactly the
same
dimensions.
So that just saved us needing to add another node and set it up manually.
Now the plain white doesn't look quite right to me, so I'm going to want to give this a material
with
a color.
You'll notice this is just a little bit different to a CSG polygon 3D where it had a material right
That's just because mesh instances have a lot more options because the CSG polygons are
intended for
prototyping.
Once I've added that, I can expand it, and under the albedo dropdown I can choose a color.
And this time I think I'm going to opt for sort of a pale yellow.
Actually.
There.
And in order to accommodate that, we want to save this as its own scene so we can instance
more of
them elsewhere.
Now, the quick way to save something we've created in a scene tree as a scene is you can right
click
Now this will set whatever we've selected as the root node of a new scene, and let us save it
straight
And in the root of this directory I'm just going to save it as Moving Hazard Scene and click
save.
So in the scene tree I'm going to click on Moving Hazard down here in the bottom left.
And you'll see we have an empty scene with just this moving hazard and the mesh instance
and the collision
shape.
So select the moving hazard at the root of the scene tree and click the Attach script button.
The first variable is going to be a vector three saying where we want the body to move to.
And the other one is going to be a float saying how long we want that movement to take.
And now, just like our size and our position, this will export a value with an X, a y and a z
value.
And we can use this to tell our box when to where to go when it's moving.
And after that, in the same way we want to set a duration for this animation, I'm going to
export
another variable and I'm going to call it duration, and I'm going to set it to be a float.
If I collapse that down and select moving Hazzard in the inspector, you'll see we have a
destination
When we go to the inspector back there, you'll see it defaults to whatever value we set in the
script.
We now want to use a tween, and we want this tween to move the animator body from where
it is to wherever
Now I find this a bit easier to use if the destination is a local distance from our body.
So for example, if the y value of our destination was one, if that destination was moving one
meter
This is going to be the object responsible for moving our shape around.
Now, the way you tween a property is we call tween dot tween property.
So the destination and the last value is how long we want it to take.
So now our tween can access this object's global position and we can animate it to a
destination.
And I'm going to set the destination to be our current global position.
That is where we currently are with this value and added on top.
So if this, as I was saying earlier, was just a y value of one meter up, our destination will be
And then we can finally use the duration, which is just going to be the duration we set in our
exported
variable.
So now when we run this well, we're going to rerun a scene with this moving hazard in it over
one second.
Our global position of our animatable body will move from where it is to wherever we set the
destination
as.
I'm going to return to level four and I'm going to find our animatable body.
I'm going to say over three seconds because it's going to take a little while to load.
And if I run that scene now, you'll see our shape is moving upwards.
So I want you to add another tween property function to return the hazard to its starting
position after
Now, it's worth noting for this that tweens use the value of variables the moment we set them
up.
So if you set a destination to be the global position, it will be the global position when the
tween
All right.
And with that said, I will see you back here in a few moments.
Welcome back.
So we want our shape to move back to where it started after it moves up.
And we are going to want to copy the stream property, because every event that happens in the
tween
So after we've moved from our starting position to our starting position plus our destination, I
want
And as I was saying a second ago, that uses the value of these variables when we first set up
the tween.
So global position is not going to update to something new after it's moved to the first
position.
Which means we can just get rid of destination, and our tween will move our body from its
starting
position all the way up, and then back down to the same starting position when this tween was
created.
We'll take three seconds to move up, and then I'll take three seconds to move down.
We want it to loop.
Thankfully, tweens have a built in function that will make them loop, and they will just
continue
to iterate back over their instructions endlessly.
The way we do that is when we create our tween, we can get Ahold of our tween.
And we have a bunch of options for controlling how our tween should behave.
And when you call set loops, you can either pass in a set number of loops you want to
perform, but
if you don't pass a set number of loops, it will continue to do the following actions indefinitely.
Now.
At the moment the movement looks a little bit mechanical and there's a really nice way we can
get around
that.
And that's tweens animate with something that are known as transition types and easings.
One extra step we can make here is we can do tween dot set trans and that will set a transition
type.
And you can see we have a whole bunch of different transition types.
We can pass in an elastic transition type an exponential one a linear one is what we're
defaulting to.
If we pass in trans sign, our tween will use a sinusoidal transition, which just looks a bit more
and it sort of has a visible momentum that changes as it moves up and down.
And if I try and fly into that, it should still behave as a hazard.
Actually it won't.
I need to set the group to be hazard because at the moment it doesn't care whether I touch it.
And let me just check what the specific tag I use is on obstacle.
I'll select that root node, I will go to the inspector and I will change to the node tab.
And I'll change from the signals section to the groups section.
And now in level four when I run it again, we should find that as I hit the moving obstacle, it
ends
There's one last little thing to set up and that is at the end of level three.
We can go over to the inspector, and we can change this file path to redirect from back to the
start
to level four.
So that's how you can use animatable bodies and how you can animate transitions with tweens.
In the next one we are going to be looking at adding audio to our scenes.
Introducing Audio
In this lecture, we are going to learn how to use the audio stream player node to play one off
sound
effects.
So for this lecture, I've provided two resources within a zip file.
And I'm going to start by taking that zip file and adding its contents to my projects.
From there, I'm going to have to ogg files within one called Death Explosion and one called
success.
Highlight both of those, and I'm going to drag them straight into my Godot project in the file
system
And I just made this file system a bit bigger, I can reset that.
I'm going to select those and drag them into the root of my project.
So they're available next to the player and next to the moving hazard.
I'm going to reset this because I've actually made my file system a bit bigger.
If you ever change the scale of any of the docs in your editor, you can go to the top bar and in
the
editor drop down, click on the Editor Layout foldout menu and click default and it will reset
everything
So with an audio file, we can either use something like an MP3 or an ogg file.
We have Ogg files here and they have the benefit of being very small.
And it's just a very compressed way of passing along audio information.
In order to play that file, we need to use an entirely new node, and that is an audio stream
player.
I'm going to open the player scene by clicking the little clipboard.
There's audio stream player that's got a little white play head, and there's one with a red play
head
Those colors indicate whether or not the node is 2D, 3D, or neither 2D nor 3D.
Something with 3D positional information will sound different depending where it is with
respect to
the camera.
We want to play this audio clip the same no matter where it is, so we're going to use a plain
old audio
stream player, the one with the white play head down here.
So I'm going to click the create button.
So this has a bunch of properties controlling how the audio will play.
And we need to select an audio stream that it will use to play a sound from.
And in this case, we're going to start by setting up our explosion sound effect.
If you look at in the Inspector at the stream property, we can either click the drop down to the
right
of it, or we can just drag our ogg file all the way from in our file system over into our stream,
Or we can click the drop down to the right and you can select the quick load option.
And when you select Quick Load it will open a view of just the valid files in your file system
that
So this will only show MP3 files, WAV files or Ogg files.
You will hear that it plays our death explosion sound effect right in the editor.
So you can hear we've got the right one set up.
If you find this volume much too loud, you can fiddle with the volume property and make that
significantly
lower.
So now with that audio stream player set up and that stream, I want to rename this node.
And in order to make this node start playing from in code, we need to learn about an entirely
new annotation.
So we've stored values in variables before we've stored floats and we've stored strings.
And that will let us do things like access its functions and properties.
And in order to do that we need to use the on Onready annotation, which is just like the export
annotation
we discussed recently.
In this particular example, we have seen where we have a parent node with a script attached to
it.
If we want that script to be able to access a child node, we need to use this following syntax.
We declare a variable.
And then after that we give a name for our variable and we can set a type for it.
But afterwards we get to a new kind of syntax and that is this dollar sign.
At the moment, because this child is an immediate child, we can just pass in a dollar sign and
the
I'll show you a bit more about how to access more complex paths.
You can let Godot generate a node path for you, which is a much more convenient way of
generating one
of these paths.
We can't access sub nodes of our script until our script has called its ready function.
So when you attach this annotation to a variable declaration, it will wait until that point.
When we have access to a sub node, we can then access its properties and call its methods.
I am going to open our player script and I'm going to make that take up the full screen.
So the very quick and easy way to create an add on ready variable declaration.
On the left I'm going to hold the control key and I'm going to drag that node into my script.
And if I let it go there, you will see it's created a whole add on ready declaration for that
variable.
So you can see here if I make that full screen, it has added the at on ready annotation because
it
knows that this variable needs to wait until the ready function is called.
It's given it a node name based on the name we gave the audio stream player.
When we renamed it, it gave it the right default type, and it gave us the path to that explosion
audio
variable.
We can use this explosion audio variable name to start calling its methods and functions.
So let's do that.
The way we can make an audio stream player play the audio stream that it has is with a
function called
play.
So in crash sequence right at the top, just after we print our debug line I'm going to access the
explosion
audio.
So explosion audio.
If I do dot play and then an open and closing parentheses, it will make that audio stream player
at
This audio stream is longer than what we just heard, because one second into that audio
playing our
level reset, our audio just got cut off partway through.
One nice way we can work around that is I'm going to go back into my crash sequence and in
the tween
interval, where I wait until I'm going to reload the current scene, I'm going to just increase the
amount of time.
We can now hear it play all the way through and get all that reverb and trailing off at the end.
With this challenge, I want you to add another audio stream player for the success sound
effect.
And then I want you to rename it to Success Audio and set its stream property to the Success
Ogg file.
And you can call the variables play function in the complete level function.
All right.
I'll leave you to that and see you back here in a few moments.
Welcome back.
I could duplicate this explosion audio, but I'm going to show you creating a new one from the
ground
up.
I will select the player root node, hit Ctrl A to open Create New Node dialogue and I already
have
audio search.
I'm going to search for Audio Stream player and click the create button with that selected.
I'm going to go down to my file system, find this success ogg file, and I'm going to drag that
into
And we can hear that playing by clicking the playing property down below it.
And I'm going to show you that working again quickly here holding control, dragging the node
and dropping
it in.
But if you want to do it manually, one other way you can do it is if you want to find out what
the
path to this node is, you can right click on it and you can click the copy Node path option in
that
contextual dialog.
If I paste now, you'll see we've got success audio because it's an immediate child.
But if, say, I had another node in the middle and I dragged this as a child of that and I copied
the
The path will be the name of the immediate child node, and then a forward slash and then the
child
we actually want.
So that's how those paths are changing.
I'm going to assign it to a node path, and that's done with the dollar sign.
So we want to play this sound effect when we successfully land the ship.
Now, as with the crash sound that actually cut off partway through.
I'm going to go into complete level, and in the tween interval part of the Tweening function,
I'm
Perfect.
We've learnt how to completely set up one off sound effects, use audio stream players and
access variables
In the next one, we are going to be adding sound effects for the rocket and toggling it with
code.
them.
For this lecture, I have provided another ogg file for our rockets audio.
In the lecture resources, download the zip file and we can move from there.
Within.
There you will find a file called Sound effects main engine thrust ogg and we are as before
going to
And if we scroll down, we will now see it is just below the other three sound effects files.
I'm going to hold shift and select all three of those ogg files.
I'm going to right click on them and you'll see we get a move slash duplicate to option in the
pop up.
We can then move all of those files into the audio directory and click move.
And you often want to use that move command rather than dragging files around, because it
does the
job of updating paths in various scenes to use whatever the new path we've moved those files
to is,
Audio still works, even though the file resource is in a new place.
I'm going to go in this audio folder and I'm going to double click on main engine thrust ogg.
So you can do things like preview the sound here if you click the play button.
But the thing I want to do is I want to make this sound loop so that if we play the rocket audio
for
a long time, eventually it will wrap back around to the start and we won't have to do any extra
programming
The way we do that is you check enable under the loop option, and once you've made that
update, you
With that all set up, we can move on to our first challenge.
So from there, I want you to add an audio stream player 3D node as a child of the player scene.
This is the 3D option that's got a slightly red icon that has positional information, and you're
just
going to add it as a child of the root of the player scene, then rename it to Rocket Audio and
update
Finally, with that done, add an Onready variable for that new rocket audio node.
Good to go.
Welcome back.
So our first step was to add an audio stream player 3D node, which is slightly distinct from
Audio
stream player.
I'm going to go to the player scene, select the player root node and hit Ctrl A to open the
Create
New Node dialog and search for Audio Stream Player 3D.
So you can see it has a red play button and this plays positional sound in 3D space.
The reason we're going to use this is it means that the sound of our ship thrusting around will
be different
depending on where we are in the actual level, which is quite a nice effect to have.
So I'm going to create that node and I am going to set its stream property.
So with this audio stream player 3D selected over in the Inspector in the stream property, I'm
going
to click the drop down to the right and click Quick Load.
And when it gets to the end it should loop back because of our looping property.
There we go.
I'm going to double click on Audio Stream Player 3D and I'm going to call it Rocket Audio.
Hit enter, we now have our Rocket Audio renamed and we want to set up our Onready
variable.
So I'm going to go to the top of this player script where the other onready variables are.
I'm going to hold control and I'm going to drag Rocket Audio in.
Or you can offload any of the other processes I showed you before to type out this full name,
which
is currently it is called Rocket Audio and it is an audio stream player 3D, unlike the audio
stream
player from last time and we just type in the name, we just gave it after a dollar sign for the
path.
We can start playing its sound when we are actually pushing the boost button, but we're going
to hit
So our previous two sound effects are one off sound effects, and they had one trigger that
would happen
once.
So if we start trying to play this sound every frame, it will constantly restart and we will get a
So we're going to need to do an extra step to make sure we don't try to play the sound if it's
already
started playing.
When we are pressing the boost button, we're going to add a new line afterwards.
So that's a variable that tells us whether or not it's currently playing and if that value is false.
So that means if we reach this point and the rocket audio is already playing this, if block won't
execute,
So let's see this new script in action and see how it actually performs.
And I'm going to push space to start boosting and the audio will start going.
And that's because we need to tell this audio stream to stop when we let go of that spacebar.
In order to stop the audio stream from playing, we could benefit from knowing about a new
keyword that
There is a complement to the if statement we've been using, and that is the else statement.
After an if statement, we can add an else statement to handle if the condition wasn't met.
This will only run if the first if block didn't do its thing.
So it's kind of like saying if not input is action pressed boost and then having that immediately
afterwards.
So essentially this lets us catch when we're not holding down the spacebar, and when we're not
holding
down the spacebar, we can stop the audio stream player from playing.
So looking back at our script, there are a few if statements and we don't want to confuse which
one
So we want.
When we don't push boost, so we want our line to be as indented as this if statement is.
I'm going to hit backspace twice to get my cursor on the same level as that if statement.
And then we're going to type else and a colon and hit enter.
And now this code will only run whenever we are not pushing the boost button.
And what I'm going to do here is stop the rocket audio from playing.
And with that, when we are playing, when we push the spacebar, the boost will play.
Our audio is working as we want, and we can mix and match and start crashing and land and
have our
crash audio play fine and have our success audio play when we land at the end of our level.
In the next one we are going to start adding particle effects into our game.
Introducing Particles
In this lecture, we are going to learn how to control the GPU particles 3D node with scripts.
We're going to be adding boost particles underneath and on the left and right side, so that when
you
start trying to turn right, booster particles on the left will fire.
When you start trying to turn left, booster particles on the right will fire.
But in order to start using these particles, we're going to need to know a little bit more about
them.
So particles are a tool for creating complicated visual effects, and they give you the power to
animate
You can use particles to create effects like fire, explosions, dust, sparks, and much more.
For example, our booster particles we're going to be putting underneath our ship.
In order to use particles, we're going to need to use a node called GPU particles 3D.
Now when we have a particles three d node, it has an emitting property that we can use to
either stop
So when emitting is set to true, particles will come out and when emitting is set to false,
particles
If you look in the associated resources for this lecture, you will find a zip file and once you've
got that downloaded, we can go ahead and start getting that introduced into our project.
So in future topics of this course, we are going to be learning how to build our own particles
from
But just to get you hitting the ground running and using the particles node, I've provided
particles
So with the zip file downloaded for these particles, we can extract that folder.
And if we look in there we will see a scene file called booster particles.
I'm just going to drag this booster particles scene into the root of our file system.
So I'm going to drag that down into the file system and drop it at the root.
I'm going to close this with this booster particles scene in our file system.
So if I select the boost particle scene, you can see it's a GPU particles 3D node.
There we can control whether it's emitting with this emitting property.
In our player, we want to put particles immediately underneath that will fire when we push the
spacebar.
That's going to show me all the scenes in my file system including this new booster particles
scene
file.
There's this cuboid bounding box around where the particles will be spawning.
We're actually going to need to move it down a little bit before we can actually see those
particles
coming out.
And then we can see there we have particles emitting underneath our ship.
I'm going to select the booster particles in the scene tree and over in the inspector I'm going to
go
And in there I'm just going to set the positions y value to a nice round number.
-1.0 even.
And now our particles are lined up with the base of our ship.
So the next step we will want to go with is we will want to make it.
Thankfully, we've already figured out all the logic for that when we were controlling the
rocket audio.
And in here I am going to want to create an onready variable for these booster particles.
So I'm going to hold control and drag the booster particles from the scene tree into our script
and
And if I expand this, we can see we have at Onready var booster particles.
It's a GPU particles 3D, and it has the correct file path.
So I'm going to go into our process function, where we detect when the player is holding the
space
bar.
And within this if block, if we are holding the space bar I want particles to emit.
We want it to be true because we want it to start emitting when they're pushing boost.
So if we're not pushing the space bar, we want to set the emitting value of these particles to
false
And you'll see if we push space particles come out the bottom.
So now we have that set up, we can do exactly the same thing for some of the particles on the
side
of the ship.
So when we are rotating left, we're going to want particles on the right side of the ship to come
out
So in order to tell what way left and right is, it's worth having a look at one of our levels.
I'm going to open level four and you will see we've got our camera over here.
So the camera being this little magenta shape that's a square with the triangles and the square
based
pyramid.
If we are looking the same way as that camera is, which we are at the moment, then our player
it's
When we're rotating left we're going to want new particles to be on the right side of the ship.
I'm going to collapse this view and I'm going to duplicate these booster particles.
And I'm going to want to move them to the right because we are going to be using these to
turn left.
I'm going to scroll down to the transform property and set them to a nice rounder number.
I'm going to set it to 0.4 on the x axis.
And these are going to be the particles on the right side of the ship.
Scrolling up to one ready variable's going to hold control and drag right booster particles into
our
script.
I must have had my cursor much further down the script, so I'm going to hit Ctrl Z to undo it.
I'm going to left click on the point where I want it to go into, and I'm going to hold Ctrl and
drag
that in.
And now we have the right boost particles going to the right part of the script.
And we are going to go to where we try to rotate left which is down here.
So if we push rotate left, we want our right booster particles to start emitting.
So I'm going to start within that if block I'm going to say right booster particles dot emitting.
Equals true.
Now we don't have an else statement like we did before, but we want to say if we're not
pushing, rotate
left, then set emitting to false.
And we do that by going to the same indentation block, the same indentation level as this.
If input is action pressed, rotate left section and we are going to say else colon and hit enter.
And on a new line within this else block we're going to set write boost particles emitting to be
false.
Equals false.
As I start pushing the A key, the boost particles on the right hand side start coming out.
For this challenge, I'm going to want you to create the matching booster particles for the left
side
of the player.
And I'm going to want you to create an onready variable with a reference to that left booster
particles,
and then control that variables emitting property when the rotate right action is pressed.
So exactly what we just did for the right booster particles, but for the opposite side of the ship.
And with that, I will see you back here in a few moments.
Welcome back.
And I'm going to change to the 3D view so that I can see these particles in action.
I'm going to duplicate the right booster particles.
So I'm going to replace right with left I'm going to get rid of the two that it added at the end.
Now we want these to be in the same position on the left, as the right ones are on the right.
And the way I'm going to do that is I'm going to select left boost particles in the inspector.
And in there I'm going to set its positions X value to be negative of what it currently is.
You could alternatively have done exactly the same thing by just dragging it around with the
gizmo,
And I'm going to hold control and drag left Boost particles into line 15 of our script here.
You can see we've got boost particles right boost particles and left boost particles.
And down there I am going to find the if statement for when we are pushing the rotate right
key.
And I'm going to want to do exactly the same thing as I did here for when we were rotating
left.
I'm going to hit Ctrl C with the setting the emitting value in rotate left the else block and
setting
So I'm at the same point in this if statement as this block is in this if statement.
And I'm going to hit Ctrl and V and that's going to enter, it's going to set the value of right
boost
particles to start emitting when we rotate right, which is incorrect at the moment.
So now when we are pushing rotate right left booster particles will start emitting and then
otherwise.
If I start playing around in the level, you should see both sides of the ship have particles start
So with that all done in the next lecture, we are going to be learning about using one shot
particles
for our ship crashing and for when it reaches the final goal.
So in this lectures resources I have provided a zip file with two one shot particles.
If you go ahead and download those resources, you will get a hold of the following zip file.
We can extract that and within we will find a folder a folder called particles.
And in there these two scenes explosion particles scene and success particles scene.
And I want you to go ahead and drag those two scenes into our file system.
So I'm going to take them and drop them into the root of our file system.
And now we should see we have I'm going to make this file system bigger so I can see what's
going on.
You can click the area between two dots and move them around and drag up and down.
You will see that we have booster particles and explosion particles scene and success particles
scene.
And now for maintenance reasons I'm going to move those all into a folder, just as we did with
audio.
So I'm going to right click on the root create a new folder I'm going to name this particles.
And I'm going to want to move those particles within the particles folder.
And the way I'm going to do that is I'm going to hold control, and I'm going to click on each of
those
scenes.
Boost particles.
Scene explosion particles, dot scene and success particles dot scene.
So I can select them all at the same time.
Right click on one of them and click on the move slash duplicate to option and then select the
particles
folder I want to move them into and click the move button.
In the top bar menu button, go down to Editor Layout and in Editor layout select default.
We want to attach them to our player, because we're going to make it so that when the player
touches
And when they touch the final goal, there's some success particles that are bright and colorful
that
We're going to do that is I'm going to right click on the player and I'm going to instantiate a
child
scene.
You see, we've got this new bounding box for this set of particles.
We want them to be in the middle of our player, and we can actually see these particles in
action right
now.
You'll notice they're not emitting the same way the booster particles are.
And that's because they are one shot particles.
And that means the particles will emit once and then afterwards they will stop.
So emitting the emitting property will set itself off once the particles have all finished
emitting.
There we are.
So we had a bunch of square particles that came out from the player, and they changed color
and they
If we go down to this time foldout menu and expand it, you will see that these particles are set
to
one shot.
If we disable that and we set the particles to be emitting, they will continuously emit.
But it's this one shot property that means the particles will only emit once, and in fact, it will
So at the moment, all of the particles emit roughly around when we set emitting to be on.
If we had explosiveness set all the way down, the particles will emit at even time intervals
across
So if I set that all the way down to zero, there will be a constant stream of particles coming
out.
And if I set that all the way to one, the particles will all emit exactly at once.
So now we know a little bit more about how we control these properties.
I am going to set one shot to be back enabled, and we can go about setting it up so that when
the player
So we want to go to our player script, and we want to create an onready variable for these
particles
And I'm going to drag those explosion particles in below the rest of our onready variables.
And you can see we have these explosion particles with the rest.
So we're going to control these in a very similar way to how we control the booster particles.
So when we've touched the floor and we start crashing and we play the explosion audio right
at the top
of there, I want to get the new particles we just added, which were called explosion particles.
And now, whenever the ship crashes, those particles will start emitting.
And because it's one shot, they will only emit once.
Once you've instantiated those success particles, you can create an Onready variable for them.
And then I want you to make those particles start emitting when the player touches the landing
pad.
All right.
Welcome back.
So we're going to follow pretty much exactly the same steps we did for those explosion
particles.
So we want to select the root node and instantiate the success particles.
So let's do that.
And we get a bunch of brightly colored spheres coming out of the player.
I'm going to save that by hitting control S and go to the script tab.
Going to go up to the top where the rest of the onready variables are declared, and I'm going to
hold
control and drag the success particles into our scene, into our script.
So let's go down to where we detect when we've touched the landing pad.
We have complete level where we play the success audio and we change the next level.
Let's run the scene and see what happens when we touch the landing pad.
Lovely.
We get a very nice series of very bright spherical particles coming out as we land.
Audio.
We've now learned how to use one shot particles, unlike plain particles that emit constantly in
our
scenes.
In the next lecture, we are going to be making our rocket look a lot more like a rocket with
additional
3D shapes.
a rocket.
So to start with, I'm going to show you how to use cylinder shape properties to try and make
us actually
have something that's got a thinner body and a point at the top.
And so to get started with, we're going to want to open our player scene.
And then when we are in there, I'm going to make what we've got as the mesh instance 3D
invisible.
At the moment.
All of the work we're going to do at the moment, we're going to want to keep within this
cylinder collision
shape we've got so that our actual gameplay will be the same regardless of how it looks,
because we're
Go over to the mesh property, click the drop down to the right and select a new cylinder mesh.
Now this cylinder, we're going to fiddle with its actual shape properties so we can control its
dimensions.
We can drag these sliders around so we can make the top radius much bigger or much smaller.
And if we make it much smaller, it comes to a point which actually I think is how I'm going to
start
here.
And now I've got this shape, I'm going to want to move it so that the top of the shape touches
the
top.
And actually, just so that we can see the dimensions a bit easier, I'm going to click on the z
axis
on our gizmo, and we will get a flat on view from the side so that we can see when these
points are
lining up.
So I'm then going to drag this mesh so that its top touches the top of our shape, which is about
there.
I think that's going to be something like 0.75m up.
If we look in our inspector, I am going to scroll down past all of that mesh information, go
down
to the transform property, and in there we can see what our Y position is set to.
I think it's worth renaming these mesh instances so that we know what parts they're referring
to, so
So I'm going to double click on this and I'm going to rename that to the cockpit.
We're now going to want to make the body that comes down, joining up to the bottom of that
cockpit.
I'm going to hit control and a add a new mesh instance 3D.
So I can just click create and add that into the scene.
We want its width to be the same as the bottom of that cockpit was.
So I'm going to expand the mesh property, and I'm going to set both the top and bottom radius
to 0.2.
And then if we move it down, it should fill out the rest of the space within our ship.
It now fills up the rest of the space to the bottom of our cylinder mesh outlined in blue.
As again, I'm going to go down to the transform property and round out whatever number I set
that to.
And now, for ease of use, I'm actually going to do some reparenting.
I'm going to take this cockpit, and I'm going to drag it so that it's a child of the body node.
So that means if we change the position of our body, the cockpit will move with it, which is
very
handy.
And actually, when we're building the rest of this ship, we're probably going to want to keep
everything
reparented to some sensible point on the ship so that as we move them around, we can move
all of the
sub pieces.
But from here, we're actually at a good spot to start trying to dive into our challenge.
All right.
So by adding new meshes to the 3D nodes and controlling their shape property, I want you to
customize
This is a good opportunity for you to experiment with all of the 3D shapes that are available
within
the mesh instance 3D node, and you just need to make sure that this fits within that cylindrical
collision
shape.
3D I was pointing out earlier, it would also be nice if you end up with three thrusters at the
bottom,
one for the main thruster and two for the left and right side thrusters, so that we can match
them
up with those particles later on, but really take a chance to flex your artistic muscles.
Maybe pick a ship you like from some piece of media and try and build that.
And with that all said and done, I will see you back here in a few moments.
Welcome back.
The rough way I'm going to have my ship look is I'm going to have a cylindrical body piece
that juts
out here, and I'm going to have a base for the thruster here, and then I'm going to have an arm
that
sticks out and a thruster pointing downwards, both on the left side and on the right side.
And then I'm going to join all of those bottom pieces together with a Taurus, which is a sort of
donut
shape.
I'm going to go to the mesh property and I'm going to add a new cylinder mesh, and I'm going
to expand
I'm going to make it 0.3m in radius at the top and 0.3m in radius at the bottom, and 0.3m tall
overall.
I want it to be a little bit more flush with the body, so I'm going to decrease those to 0.25.
So I'm actually going to move that up to about here, which I think is 0.25m up.
So I'm going to go down to the transform property, and I'm going to set that to a rounded
number which
is 0.25m up.
I'm now going to use something similar to make the base larger where the booster is.
So I'm going to start off by duplicating this midriff I'm going to duplicate it.
If I open this mesh property up and I say start increasing its top radius to something like 0.5,
you'll
notice both of these shapes have updated because I duplicated the previous midriff.
We could replace the mesh in here with a new one, but we want to keep the same properties,
so that's
a bit of hassle.
The actual way we'll separate these shapes is via undo what I did there.
And at the bottom of this list there is the make unique option.
That's going to just turn this mesh into an entirely unique mesh and make its changes, not
share between
And now if I increase that top radius you'll see this one changes but the old one doesn't.
Going to undo that I'm actually just going to make this taller.
And I'm going to move it down to the base and try and get it to line up.
Let's go into Z view so I can see when it's lining up, and I'm going to drag it up a bit just so it
So now we've got a big thruster at the bottom, and we can start moving on to making these
arms that
So the way I'm going to make these arms is I'm going to have a cube that juts out, and then
another
I'm going to hit control A with the body selected add a new mesh instance 3D.
And I'm going to go to the mesh property and select a box mesh.
I'm going to make it 0.2m on the x axis, 0.2m on the z axis, because that's its depth.
So now I'm going to move this arm to the left so we can see it.
I'm going to use this blue arc to control its rotation around the z axis.
And I'm going to rotate it around the z axis so that it points towards this middle section of the
ship.
I want it to be long enough that it juts out, but also so that we can't see the corner cropping out.
So I don't want to leave this harsh edge jutting out, so I'm going to actually need to make it a
bit
longer.
At about works.
I might need to rotate it a bit more.
There we are.
If I look around the ship, you can see it's flush with the actual body.
In fact, it would be nice from my perspective if it was a bit closer to the main thruster.
Let's go back in and let's angle it down a bit more and bring it just a bit closer to the bottom
thruster.
I know this is the left arm because I remember from earlier that the positive x direction.
So where this red arrow is pointing is to the right from the games perspective.
And I'm going to add a capsule as a child of it, and that capsule is going to be the last the
thruster
on the left.
So I'm going to select that left arm, because I want this to be a child of that arm.
So as I move the arm around, the thruster will move with it.
I'm going to select the left arm, hit control A and add a mesh instance 3D.
So in the mesh property I'm going to go over and select capsule mesh.
I'm going to make it 0.3m, 0.2m at the top, 0.2m at the bottom, and I'm going to make it 0.3m
tall.
Two meters is actually a lot wider than two meters for the boxes.
I'm going to rotate this around and I'm going to move it down a bit.
That looks good, but it's not quite tall enough to reach the top, so let's increase its height a bit.
I'm going to increase the height to 0.4 and then move it up a little.
I want the bottom to be a constant width, so it is just a cylinder coming out at that point.
If we want to make this move over to the right, we do need to do one extra step.
We're going to want this to rotate about its y axis so that it's facing the right way.
I'm going to rotate it around the y axis by with this left arm to selected.
Go down to the transform property and set its rotations y value to 180.
So if it's rotated around there it is now a mirror reflection around the middle.
And I can now invert its position if I take its positions x value and I get rid of the minus sign,
it will now be mirrored about the middle of the ship and it will be at the same point the left
arm is,
but this time on the right and with the correct orientation.
But our name is wrong at the moment because it's still called Left Arm.
The last step I wanted to do for this show, because I think that's looking pretty neat at the
moment,
So I'm going to select the body, hit Ctrl A, add a new mesh instance 3D.
And in here I am going to add a new mesh property.
I'm going to select a Taurus mesh, and a Taurus is a shape much like a donut.
And I'm going to want this ring to go through each of the thrusters on the outer edge of the
ship.
And I think that's going to be around about 0.4m on the inside and 0.5m on the outside.
So the two properties we've got here are the distance from the middle to the inside of the ring,
and
So with an inner radius of 0.4m, we've gone 0.4m and our donut shape has started.
I'm going to drag this down to line up with the thrusters and see how that looks.
So one thing we can do at the moment, because my thrusters are a bit up, we can actually
move these
particles so that they emit from within where the thrusters are.
So I'm going to go up in my scene tree and I'm going to find my left booster particles.
And I'm just going to move them up and to the left a bit so that they're inside this left booster.
And I'm actually going to rotate them ever so slightly so that they come out at a bit of an angle
down
to the left.
And then I'm going to do exactly the same thing for the right booster particles.
So I'm going to select the right booster particles, move them up and to the right and use this
blue
We have constructed a new, much more rocket looking ship out of component mesh instance
3DS and learnt
about some new shapes that we can create with those nodes.
In the next lecture, we are going to go on and start adding colour to our ship and learn how to
use
standard materials in a bit more detail and do things like save them and reuse them.
And in order to do that, we will be learning how to save colors to reuse across a variety of
objects.
So the way I'm going to go about adding colors is I'm going to make it all a uniform red color.
I am going to create that red color on the body to start with, because we're going to need to add
this
So I'm going to select the body for this ship in the scene tree.
And I'm going to scroll up to find the geometry dropdown under Geometry Instance 3D.
Fold out that geometry menu and we'll have material override.
If we expand this material, we can go down to the albedo property, and in the albedo property
we can
I'm going to click on the color property to open the color picker.
Drag this value down a bit so I can see the colors I'm dealing with and find a red.
I might make this a little bit darker, so I'm going to drag that down a bit, but that's quite a nice
What I'm going to want to do is I'm going to want to save this material I've got as a resource,
and
then I'm going to apply it to all of the other parts of our ship.
And the way I'm going to do that is I'm going to scroll up to this material override, where this
material
I just made is if I click this drop down to the right of it, you can see there are options for
loading
And when we save a material, it gets added to our file system as another resource that we can
drag
and drop.
So I'm going to click save and I'm going to name this ship Red material.
And I'm just going to save that in the root directory along with where the player scene is.
And if I double click on that it will open it in the inspector and we can edit it there.
What we could do is we could click on, say, the cockpit of our ship, go to that same geometry
property
and under material override, click the drop down to the right of it and quick quick load.
And if we do that we'd be able to select our one available material we have saved in our file
system.
But another neat thing we can do is you can just drag this ship material from down in our file
system
It's quick and easy, but I have noticed it has some quirks.
If you drag this material over a body that already has a material on it, it seems to remove the
material
that's there.
I think because it tries to drop the one you've got in and it replaces the old reference or
something.
I assume it's a bug, but it's worth bearing in mind that you need to try and avoid hovering over
a
So I'm just going to drag this material over all the individual parts of this ship.
So with that all said and done, it's time for a challenge.
You've made a custom ship with custom colors, all in constrained conditions, something a bit
unique
to you and your challenge, should you choose to accept it, is to share what you've created with
the
community.
We have a variety of social media platforms where you can share a picture of what you've
created.
You could go to the Game Dev forum or the Game Dev Discord server, or you can tag game
dev directly
This is a great opportunity for you to see what others have created and to show off your own
artistic
talents.
So I'm very excited to see what you've made, and I will see you back here in a few moments.
All right.
Welcome back.
That has been a quick look at using standard materials to set the color of our ship, as well as
some
ways to save and reuse materials, as well as applying them to a variety of mesh instances.
In the next lecture, we are going to be moving on to using CSG shapes to filling out the rest of
our
Building Backgrounds
In this lecture, we will start using shapes to flesh out the backgrounds of our levels.
So to start with, we're going to want to return to levels seen.
And we're going to use CSG shapes very similar to our floor to create a bounding box around
our level
So the first thing I'm going to do is I am going to select the floor and I'm going to create a new
node
So I'm going to hit control A to open the Create New Node dialog.
One important thing we're going to want is we're going to want the material that's on our floor,
because
So I'm going to select the floor node and its material in its material property.
I'm going to click the drop down to the right and select the copy option.
This will let us copy the resource that we can paste into other slots in inspectors that accept a
material
property.
Now.
One point a convenient thing CSG boxers do is if a parent has some specific properties like
use collision
I'm going to make it four meters on the x axis and four meters on the z axis.
I'm going to just drag it over to the left to make a left wall and use this blue Z axis rotation to
There we are.
So we have one more, and I'm just going to copy and paste this around until we have an entire
bounding
box.
Now we have another node called wall two in the same place.
I can move that straight up and use this blue Z rotation to rotate it so that after angling to the
left
at the bottom, it's now going to the right and creating an overhang over the head of us.
And this is fine for a wall on the left side of my play area, I think.
So it's horizontal.
Let's change to full side view with that Z button on the gizmo in the top right.
I'm holding shift and clicking the middle mouse button to move around and scrolling in with
my mouse
wheel, and I'm going to move that over to the right a bit and use this blue Z axis rotation to
angle
I think I can move it a bit higher up, and I think I'm happy with that broad shape.
I'm going to copy it over so that we can start bridging this gap over to where the landing pad
is.
And I think I'm okay having a bit of a jutting, jagged shape in the rocky walls of whatever
location
And so I'm going to duplicate it one more time and move it over further to the right.
And I'm going to try and line it up just a little bit with the existing wall.
So I'm going to copy one of my wall nodes so I don't need to rename it.
Whenever we add a new node it gives it a new unique number until it has a unique name.
I just moved wall three below wall two so that all of my numbered walls are ordered
numerically.
I'm going to move this new wall three over to the right hand side of the landing point and drag
this
So one thing we will want to do is see how much of the level we can actually see with our
camera.
So I'm going to collapse this floor and I'm going to select the camera 3D node for this level
and click
I'm going to enter distraction free mode so we can see more of that viewport.
And we can see right now this isn't quite doing the trick.
We'd rather see more of the bounding area.
So I'm actually going to go ahead and move the camera back and up a bit.
And I'm going to move it further back and its distance away from the play area is this z value.
So let's increase that z value, move it a bit further back, and then let's move it a bit further up
so we can see that jagged roof a bit more and a distraction free mode.
We can now see a bunch of the floor at the bottom, and not very much at the top.
We can actually afford to go a bit higher, so I'm going to move that even higher up.
And there we have all of this new terrain around the edge of our level.
Now I actually think we could use a little bit more vertical space because we're going to have
things
like things to dodge around the top on level three and around the bottom to dodge.
Now.
I'm going to exit this camera preview mode, close that bottom part, and I'm just going to move
all
So I'm going to just click on that wall on the left and move that up a bit.
Can afford to move the middle one just a little bit higher to.
There we go.
There we go.
We have a bunch of area around the edge of the map being contained.
So given we've added shapes to the sides and top of our level, I want you to go ahead and add
more
And this is a chance for you to flex your creative muscles and imagine what kind of confined
space you
And with that, I will leave you to go ahead and create a background with more shapes.
Welcome back.
So for my background, I want a bunch of jagged blocks looking rather similar to these shapes
we have
In order to do that, I'm going to exit this preview mode and I am going to go ahead and copy
one of
I'm going to drag it down below the walls and ceilings of this section, and I'm going to call it
background.
Rock.
So it is now behind everything else, and I'm going to move it to the side and angle it a bit, and
I'm just going to end up with a bunch of jutting out shapes, and I'm going to use whatever
rotation
I want.
And I think I'm just going to have a series of shapes like that.
Maybe move it down a bit and then duplicate it again, move it over and move this one up a bit.
And try and change over to the view from the front so they look rather symmetrical at the
moment.
I'm going to move that one over a bit so that they intersect and move it down.
And we're really just going to populate this shape with anything we think will look interesting.
I might actually want to frame the center a bit more with these shapes.
So I'm going to select both background rock two and three by holding shift and clicking on
them in the
scene tree.
And then I'm going to select this block on the left and move it over to the left.
Then going to duplicate lock three and move it up to the ceiling and use this y axis to rotate it
around
so that we have another another prism seeming to come about from above.
And it's just going to look like some very cubic blocks, a little bit like bismuth.
I'm going to make it three meters wide and three meters tall instead, but the same height.
And I'm just going to have a bunch of sharp, jagged rocks coming from the ceiling at fairly
similar
directions.
I'm going to leave that one going off to the side so that it looks like we're rounding out the
cavern
a bit.
So I'm going to duplicate background rock to move it to the right and move it down.
There's kind of an empty spot up here where it'd be nice to have a rock.
And there's an empty spot down here where it'd be nice to have a rock.
So I'm going to duplicate background rock seven, move it across to the right and down again.
Now this space is filled out and I'm going to select this block behind us on the left.
And I'm going to duplicate it and move it to the right and then up.
And then I'm going to move it back into the view so that it becomes a bit smaller for our
perspective.
So we just have a bunch of jagged rocks filling up the back of our view that we can explore,
and the
And I'm going to try and land my ship over here, and that's all fine.
And we're going to encounter our first issue, which is that background isn't applied to all of
our
levels.
If we go into our other scenes, we can replace the floor node with this new entire background
scene,
There it is.
It's called floor though, so we can get rid of the old floor node that is just the base and hit the
You can also delete by right clicking and selecting delete nodes at the bottom, and then
clicking confirm.
And I'm going to repeat that for level three and four.
This time I'm going to delete the floor node first because I know it's going to rename the other
node
if I don't do it first.
We now have a background here, and in level four we can get rid of the floor.
Right click on the root, instantiate a child scene, select background, click open and we're done.
So now if I run that and as I progress through the level we will have a whole bunch of different
backgrounds.
I've actually just noticed something, and that is that I adjusted the camera for level one, but I
I'm going to show you a neat way you can update a node's properties, and that is by copying a
node's
properties.
So if I click on the camera 3D and scroll down you can see it's it's y position is about 5.8 and
its
We can copy all of the properties associated with this node and paste them onto other nodes.
What you'll do is you'll click this little screwdriver and spanner in the top right of the camera
3D,
and you will select Copy Properties, and that's going to copy every property this node has.
If I then go onto level two and I select the camera 3D, you can see where it is at the moment.
Right here.
If I click the spanner again and I click Paste Properties, it has now moved back and up because
it's
Go to level three.
Save.
And now if we run when we move on to the next level, it will have the same view that we have
here.
So let's land.
And now level two has this new view that's further back and with this background.
And with that, we've set up an interesting background for our levels.
In the next lecture, we are going to handle a bit more of the lighting and the world
environment to
So way back at the start of our project, we set up a default world environment and directional
light
based on the preview, directional light and world environment that are available in these three
dots
at the top.
We can start customizing those a bit to make our game look how we want.
Our world environment is responsible for this background, ground area and sky area we get.
And I'm going to just shift that over to a flat color so that it's not obvious that there's stuff
going
on in the background.
So in order to do that, we're going to want to fiddle with our world environment on one of our
levels.
It doesn't matter which just one where we've set up this background.
Let's go over to the World Environment node in the scene tree and select it.
In this node's environment dropdown, while its environment property, you get access to a ton
of features
You get things like glow options, fog options, ambient occlusion, a bunch of stuff, and the
property
that controls how our background looks is in this background fold out menu.
So at the moment it's set to Sky and you can control how that sky looks.
And in the dropdown to the right of it select the custom color option.
And that will let us just pick a flat color to use as the background for our scene.
So in this environment in the mode property, click the dropdown to the right and select
Custom Color.
Now having a black background is fine, but you'll notice the lighting's also changed.
The reason our lighting's changed is because of this ambient light fold out menu.
At the moment it's using the background color to determine how our ambient light should
look, but we
So we use that previous sky for the ambient light, but when it's drawing the background, it will
just
Now I'm actually going to do a neat trick to blend our color in a bit.
I'm going to go to our camera 3D, and I'm going to go into preview mode so I can see what the
camera
can see.
And I want to pick a color for this background that blends in a bit more with the background
than being
And the way I'm going to do that is in this background out menu for the world environment, it
has a
color property.
If we click on the color picker for that color property, there is this little eyedropper button.
And that lets us pick somewhere in our level to select a color from for this background color.
And now you'll see as I move my mouse around the screen it is going to eyedrop whatever
color I'm hovering
over.
So I could set my background to be this red on our ship, or this green on our landing pad, or
this
I'm going to select an area in shadow that's similar to this, an area of shadow on one of the
background
rocks, so that I get a dark brown as my starting point.
I'm going to go one step further, though, because I want this to be a bit darker than that area in
shadow is.
And the way I'm going to do that is I'm going to reopen this color.
Now, I've selected that brown baseline, and I'm going to change over to the hue, Saturation
and Value
tab.
This is going to let us alter the saturation and value for this color.
And I'm just going to decrease the value from 14 down to let's say seven.
The color is the same hue at least, but it's all darker.
And if I try running this level, it should just blend in a bit nicer than it does before.
So it looks almost believably like that's a background Cavan color behind the rest of the level
we've
set up.
So now we've got a background color sorted, we can start fiddling with our lighting.
I'm going to exit the preview mode for this camera, and I'm going to start looking at this
directional
light.
It doesn't matter where it is, it is globally applied in a direction, and that direction is shown
It's just going to, no matter where we are, have light coming down at this angle.
Now at the moment that light is coming from behind our stage.
So if I rotate round, the back of our stage is well lit and this area is in shadow, which doesn't
necessarily look bad because it's dark and cavernous, but I do want to have the front of our
stage
lit.
So we could adjust this by just using the arcs, the rotating arcs on the edge of the gizmo.
And you can see if I select the y axis, the green arc, and rotate it around, we can pan things
until
I want to set this directional light to that I found while messing around earlier.
And so you can see that that is it's rotated so that the front is lit up.
And if I change back to the camera view and preview, you can see more of this as well.
Lit.
One extra step I want to go through here is I actually want to make this directional light give
less
light to our scene, because we're going to add some more lights into our level later on.
So to make this a bit more ambient, I'm going to select the directional light I was just editing.
And I'm going to scroll up to the top and see the properties for this light.
Now you have a bunch of options like setting the color of the light, and the energy of the light
is
So I'm going to make this directional light give half the energy it is at the moment.
So now we've edited our directional light 3D and our world environment.
We're going to start to want applying these changes that are on these nodes to the other levels.
Now we could go ahead and step through each level and copy and paste our values across.
But we added a node recently that will help us and that is our background scene, this one with
the
floor where we can go ahead and move this directional light 3D into that floor scene, and then
every
scene that's instantiated, this will have a directional light that is pointing in the right direction.
So the way I'm going to move it across is we can either right click on the directional light and
click
Or if we want to be a bit more diligent and make sure we don't accidentally lose this node
somewhere,
we can copy and paste it.
I'm going to open the floor scene and I'm going to select the route.
And that's going to add this directional light 3D as a child of this scene.
So you can see this scene right here has lighting set up in the same orientation as the last one.
So now it's got the old brightness it did before we decreased the energy.
So I'm just going to go ahead and get rid of this old directional light 3D.
So we've just moved our updated directional light into our background scene.
I want you to go ahead and do the same thing, but move the world environment into the
background scene.
So you're going to want to either cut or copy that world environment, put it in the background,
and
then delete the old world environment from the main level scene.
Welcome back.
So in order to remove this wild environment and add it to the floor, this time I'm going to cut
this
On the way back, I'm going to right click on the world environment and select cut.
But if I go into the floor, click on the floor scene, enter, open it in the editor and I'm going
So now every scene that adds this background will get that world environment with the nice
shade of
I am now going to do a bit of cleaning up, and I am going to remove those two unnecessary
lights and
I hold control to select them both in the scene tree and hit the delete key and hit enter.
And it's using that world environment and light from the background.
Hit delete.
Hit enter and save.
Hit delete.
The last thing I want to do, as far as lighting is concerned, is I want to go straight into this
background
scene.
So I'm going to make my changes in here now so that they're applied to all of those levels at
once.
I'm going to hit Ctrl A and search for Omni Light 3D.
It spreads a light out in all directions, unlike the directional light, which all casts it in one
specific direction.
So you can just about see it's lighting up ever such a little around the back.
The reason I want some omni lights in this scene is because of this big, hard shadow that's cast
on
the background.
I just want to soften those up a bit and make it a bit less obvious that this front, this front area
If I go over to the inspector and look under the Omni dropdown, we have a range property.
If I increase that, you will see that the white gizmo is increasing in size.
I think that's a nice large range, but you'll see it's having a very little influence on the
background.
And that controls how quickly the light drops off as we get further away from the center.
So when you have a curve like this, you can either click on it and drag down, and you will
make it
Or if you raise it up, you will see very quickly that it is spreading the light much further before
dropping off.
And that is if you right click on the curve you get a bunch of preset curve options.
So there's ease in which is that first option where it dropped off faster and ease out where it
dropped
So I'm going to select this ease out option that set this to 0.5.
And you can see we have a light that is quite distinctly spreading more around the background.
So I'm going to select it in the scene tree and hit control and D.
And I'm going to move this one over to the left to light up the left side of our scene.
And I'm going to duplicate it once more and use the gizmo to drag it all the way over to the
right.
It looks like there is a lot of light in the center of our scene, and less at the edge.
So with that all in place, I'm going to run the scene and see how it looks.
Let's fly to the end and see how the next one with objects in the middle look.
And that is how our scene is looking, with all of its new lighting and world environment
options.
In the next lecture, we are going to look into wrapping up this project and learning how to
export
We can easily export to windows, Linux, Mac, iOS, Android and web.
The export options will drastically increase the file size of the engine.
So we are going to need to download templates for whatever platform we want to distribute to.
So if we want to distribute to windows, we will need to download the windows templates.
And if we want to export to web we will need to download the web templates.
Thankfully, that's all doable from in the export page for the engine.
We'll find our export options in the top bar in the project dropdown and under export.
If you click that export button, you will open this export window where we can add presets for
the
If you click this add button in the top middle, you will see all the available platforms we can
build
for.
I am going to select Windows Desktop because I am on windows, and you will see we get a
bunch of config
I'm just going to make this full screen green so I can see what's going on.
And you can see it says we have no export templates found at the expected path.
That's what I was saying about we need to download templates for whatever platform we want
to distribute
to.
So if you click this Manage Export Templates button at the bottom, it will give us a prompt
where we
So it's already figured out that we want to download templates for the version of the engine
we're using,
which is 4.1.1, and we can just click the download and install button on the right, and it will
download
those from whatever the best available mirror is.
And that's just because of all the necessary binaries for distributing for that platform.
I'm just going to wait for this to download and see you back here in a moment.
Okay.
It has returned me to that export template manager, and it is telling me in the top right that
export
I'm going to click the project button in the top left again click export.
And now you can see all of those errors are gone.
Although at this point you may actually see a little message about the RC edit tool at the
bottom.
So there are a bunch of options on the right for how our project should export.
At the moment the player will receive an EXE file and a PAC file.
I'm going to go down a bit further and look at the rest of the options we can pick.
Icons that I'll talk about a little bit more later on.
I'm going to put the game name in the product name option and I'm going to say Project Boost
again.
They differ a little, but you will typically want to export projects.
And that will open a directory viewer so that we can choose where we want to export our
project.
If you leave that enabled when the game runs, a console will pop up, which can help give you
some
testing information, which is useful if there's an error when or some kind of issue in your
exported
project, but don't need that for the moment, I'm going to disable it, and I'm just going to save
And this is what I was mentioning a few moments ago about the icon.
You need to go through a few special steps if you want to customize the icon for an
application on windows.
Going to close this export window, and I'm going to open the file from my file system.
So now Windows Explorer has this area open which has my audio level folder particles folder
or the rest
And you can see we've got Project Boost with the Godot icon.
You can see it open very fast, and my game is running and I can fly around and land and
progress through
the levels.
So with that exported, you can send that to your friends or whoever you want to try out your
game.
So for the challenge, I want you to go back to the player script, and I want you to add a check
if
If they are pressing the cancel action, I want you to call get Dot quit so that the game will
close.
So in short, while the player is playing, they can hit the escape key and when they do, the
application
will close.
After you've done that, I want you to export the game again and check the player can quit the
game
This is all an exercise to ensure that you've got in your mind how you can export the game.
So I'll leave you to that and I will show you it in a few moments.
Welcome back.
Going to close that explorer and I'm going to open my player script.
At the moment we are saying if input is action pressed and then checking the action that was
just pressed.
So let's go down to the end of this process function, which is around here on line 40 for me,
I'm
going to hit Enter and Backspace so that I'm indented to the same level.
All the rest of these other functions are I'm going to say if input dot is action pressed.
Now actually I'm going to say is in is action just pressed which is a variation of his action
pressed
It will only fire the first time the key went down.
We should see the same functionality for both, but it's just a little bit more technically correct
to use.
I'm going to put a colon at the end and hit enter so that we enter this indented part of the if
statement
So that should make it so that while we're playing the game, if we ever hit the escape key, the
game
will close.
I'm going to test that out quickly now before I export it, to make sure everything's behaving as
I
expect.
I'm going to fly up a bit and I'm going to hit the escape key and it quit.
Perfect.
So as before in the top bar we're going to click the project dropdown.
And we are going to select the export option from that dropdown menu.
The option we want it to click to export was Export Project on the left here.
And then I'm just going to overwrite this old Project Boost file.
I'm just going to click save.
In this Save a File dialog it's going to say do we want to overwrite it.
And now we can close it and we can try running our game.
So I'm going to open that file system again I'm going to go to the file system open it in the file
manager.
And I'm going to find the game and I am going to run it.
And that is how you export your projects so that you can have other users try out your games.
In the next and final lecture, we will be doing a bit of a wrap up and talking about various
ways you