Skip to content

3D Intro

This is a guide for making a 3-dimentional game in Godot. If you are unfamiliar with Godot, check out the Godot basics doc.

Making the project

Making the project is just as easy as 2D. Godot new project window

Make sure your project is set to Forward+.

Create root node, 3D Scene highlighted

Set the root node to 3D and your project is set up!
Although, go ahead and save the scene with Scene > Save Scene so you have the scene file saved.

Before adding things to your scene, you should know how to move around in the viewport.
Press down the middle mouse button to rotate the camera. Zoom in and out by scrolling. Shift+Middle Mouse to pan. Right click to turn and while right click is down you can press WASD-QE to fly. Press F to recentre the camera on the selected object.

Making the player

Basic player and platform

First, you’re going to want to set up a platform for the player to stand on.

  1. Add a StaticBody3D as a child of Node3D.
  2. Add MeshInstance3D and CollisionShape3D as a child of StaticBody2D.
  3. In the inspector on the right, set MeshInstance3D’s ‘Mesh’ property to New PlaneMesh. Set the CollisionShape3D’s ‘Shape’ property to New BoxShape3D.
  4. Select CollisionShape3D in the scene tree and use the orange dots to shape the BoxShape3D to the same shape and size as the plane.
  5. As a child of Node3D, add CharacterBody3D.
  6. Add as a child of CharacterBody3D add Camera3D and CollisionShape3D.
  7. Set the collision shape to capsule.
  8. Select the CharacterBody3D and move it up in the viewport until it’s on top of the plane.
  9. Move the camera up so it’s where the ‘head’ should be on the character.
  10. Give the CharacterBody3D a script and leave it as the default template script.
  11. One final step, add a DirectionalLight3D as a child of Node3D and rotate it to point down, this can be anywhere in the scene.

Phew! That was some setup, your scene should look something like this: Scene with player Now when you play the game and press down on the arrow keys you should move backwards off the platform and fall off, you should see the platform briefly as you fall.

First person camera

Most modern 3D games have a first person camera, which can be pretty complicated. Open the script on your player. In this script, add these lines below var gravity and above func _physics_process(delta)::

# Get the player camera
@onready var main_camera := $Camera3D
# Make the camera variables
var camera_rotation = Vector2(0, 0)
var mouse_sensitivity := 0.005
func _ready() -> void:
# Remove the mouse from the screen and just capture its movement
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event) -> void:
# If escape is pressed reveal the mouse
if event.is_action_pressed("ui_cancel"):
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
# Get the mouse movement
if event is InputEventMouseMotion:
# Get how much the mouse has moved and pass it onto the camera_look function
var relative_position = event.relative * mouse_sensitivity
camera_look(relative_position)
# Rotate the camera
func camera_look(movement: Vector2) -> void:
# Add how much the camera has moved to the camera rotation
camera_rotation += movement
# Stop the player from making the camera go upside down by looking too far up and down
camera_rotation.y = clamp(camera_rotation.y, deg_to_rad(-90), deg_to_rad(90))
# Reset the transform basis
transform.basis = Basis()
main_camera.transform.basis = Basis()
# Finally rotate the object, the player and camera needs to rotate on the x and only the camera should rotate on the y
rotate_object_local(Vector3.UP, -camera_rotation.x)
main_camera.rotate_object_local(Vector3.RIGHT, -camera_rotation.y)

Changing the controls

The mouse sensitivity variable controls how fast the camera moves, change it to suit your preference.

This is all you need for a basic character controller, but, as is good practice, you should change the input keys.

Go to Project > Project Settings… > Input Map and in Add New Action add ‘forward’, ‘left’, ‘backward’, ‘right’, and ‘jump’.

Press the plus button next to each one and press the key you would like them to be.
It is recommended ‘forward’ should be W, ‘left’ should be A, ‘backward’ should be S, ‘right’ should be D, and ‘jump’ should be spacebar.

In your script, replace ‘ui_up’ with ‘forward’, ‘ui_left’ with ‘left’, ‘ui_down’ with ‘backward’, ‘ui_right’ with ‘right’, and ‘ui_accept’ with ‘jump’.

‘ui_cancel’ does not need to be changed, since it would be the key you press to exit anyway.

Making the world

More platforms

Now that you have a player, you need more platforms to jump on. Copy the StaticBody3D node and paste it as a child of Node3D.

Press R to change to scale mode and enlarge the StaticBody3D with the green square, use Shift to scale equally on all sides.
While we’re at it, use E to rotate the platform slightly and W to move it to the side so you have to jump to get to the platform.

You can go back to the select tool with Q.

Play the game and now you have another platform!

Although, if you’re paying attention, you might notice the warning sign on the StaticBody3D. To fix this, reset the size of your StaticBody3D by either pressing CTRL+Z or selecting the reset button in the inspector on the scale, which is found under Node3D > Transform.

Then select the MeshInstance3D and use scale mode to increase its size, and then select the CollisionShape3D with select mode and use the orange dots to increase its size to match the MeshInstance3D.

You might notice the collision shape is changing both collision shapes, for this new platform and the original one. To fix that you’ll need to select the CollisionShape3D and make a new BoxShape3D in the inspector since it’s still using the same BoxShape3D as the previous platform.

A better way of making multiple platforms is to save the platform as a scene and then copy paste the scene.
Save either platform as a scene by right clicking the static body and selecting Save Branch as Scene.

Interaction

You think pressing a button is easy?
You think it’s just simple to add a thing that you walk up to and press a button to interact with when looking at it.

You were wrong, let’s make a button that makes some text appear on the screen.

The text

First, the text. As a child of Camera3D, add Label. Give the label some text and move it to the center of the feint camera box.

It should look something like this: Label Feel free to change the label to a RichTextLabel and mess around with making it look pretty.

After making your text, select your label and, in the inspector, go to CanvasItem > Visibility and turn Visible off, we will be making it visible with code.

The button and raycast

Add a new StaticBody3D, with a mesh and collider. The only difference this time is to make it a floating cube instead of a plane.

Select your new static body and go to the Node tab, which is found next to the inspector tab. Go to groups and type in “Button” and press Add.

Add a RayCast3D as a child of your Camera3D and move it to aim in the same direction as the camera and move it to the same position as where the camera originates.
Your button and ray cast should look something like this: Button and ray cast Then, decrease the ray cast’s target position’s y to -3 or lower.

Scripting

Now, go to the script on your player and add an @onready variable for the ray cast and label similar to how the main_camera is. When you have @onready var your_var_name = you can just drag the node from the scene tree into the script, and it will automatically fill in the variable path and add $.

Next add the action for your interact button, like you did for the movement keys. E or F are good buttons for basic world interaction, and name it something like ‘interact’.

Finally, somewhere in your _physics_process(delta) function, probably after the jumping code, check if the input action just pressed was “interact”. If it was, get the collider from the ray cast and check if it’s not null, then check if it’s in the “Button” group, and if it is set the label to visible.

if Input.is_action_just_pressed("interact"):
var object = ray_cast.get_collider()
if object != null:
if object.is_in_group("Button"):
label.visible = true

Boom! Interaction. That might not have seemed very difficult, but knowing to use groups and ray casts is something that’s difficult to just figure out of the blue.

Now if you play the game, look at the cube, and press your interaction button it should show text on screen. This is a game. What you have made is a game. It might not look like it, but if you had beautiful art it would.

If you made some 3D models of platforms, a button, a character, and added a skybox it would look like a real game. That’s truly the only difference. Well that and maybe a goal.

What next?

Make a game!

How?

Lots of googling and frustration as you figure things out. The Godot docs are your best friend. If you haven’t been following along with the coding portions, then try going back to the basics guide and do the challenges near the end.

What?

Plan out a small game. Don’t plan out the next Skyrim, plan out a small game that you can make in a day, then a game you can make in a week, then a month, and eventually create your masterpiece!

If your goal is to make this a job, show a game company your game portfolio after making your masterpiece and help make someone else’s masterpiece. Here is a list of game developers in New Zealand. You should try making games for your portfolio in the software they use before applying. Godot is unlikely to be used, but your time has not been wasted since it still uses the same fundamentals and many indie studios are moving to Godot. Godot is also expecially good for learning high level concepts.

An even better option would be to join a game jam, which is a competition where you make a game in a short amount of time. They are wildly popular and are absolutely the best way to learn and dip your toes in new areas you haven’t before.
Just keep in mind, there’s nothing stopping you from doing anything. Just because you haven’t made a top-down game, modelled terrain in Blender, or made a 2.5D game doesn’t mean you can’t learn how to in the short span of a game jam.