Hour 13. 3D Graphics
What You’ll Learn in This Hour:
Adding 3D nodes to your game
Importing meshes and models
Working in the 3D editor view
Manipulating 3D objects
Placing, enabling, and scripting cameras
So far, everything in this book has been in 2D. It’s simple, straightforward, and cozy, and it’s easy to understand. But sometimes, you want
more—an extra dimension or a different lens through which to view your game. Sometimes, you want three sides of the coin. That’s why we’ll
explore 3D graphics in this hour.
In this hour, you’ll learn how to add 3D objects to your game and manipulate them in the editor and through code, and how to set up cameras to
view your game properly.
Spatial Node
Godot was built from the ground up to fully support 2D and 3D. Because of that, everything in 3D works and looks very similar to the process in
2D. Just as 2D nodes have a base node called
Node2D and GUI nodes have a base node called
Control, the base node of all 3D
nodes is the
Spatial node.
Just like the
Spatial node, all 3D nodes have a red color. And if you know how to use a certain 2D node, there’s a good chance you’ll find
the same node for 3D simply by removing the letters “2D” from the node name.
Let’s add a
Spatial node to a scene.
The New Transform
In the inspector, take a look at the transform properties for this node (Figure 13.1). You’ll notice that it looks similar to the 2D transform, yet
slightly different. The reason for this, of course, is that we now have a th
i
rd axis.
FIGURE 13.1
The new transform properties, which are present in every 3D node.
Just as every 2D node has a position, a rotation degree, and a scale, every 3D node has a translation, a rotation, and a scale.
Translation: the offset of this node from the origin of the scene.
Rotation: the rotation of this node, in degrees, around each axis.
Scale: the scale of this node along each axis.
If you look in the 3D editor, the “origin of the scene” is depicted by the point where the three axes (red, green, and blue) meet (Figure 13.2).
FIGURE 13.2
The origin of the scene, shown in the editor. In code, it’s simply the point (0,0,0).
With 3D nodes, an additional property is present: transform. This is a matrix of 12 numbers, and you can use it to set translation, rotation, and
scale at the same time. This requires complex math, so it won’t be discussed further here.
The Three Axes
In 2D, everyone knows there’s an x-axis that runs horizontally, and a y-axis that runs vertically. But how does this translate to 3D? Well, there
are two schools of thought:
Yis up: The x-axis is left/right, the y-axis is up/down, and the z-axis is forward/backward.
Z is up: The x-axis is left/right, the y-axis is forward/backward, and the z-axis is up/down.
These differences stem from the background of people using 3D. For example, the “z is up” version is usually attributed to architects. They first
draw a floor plan on paper in 2D (using x and y axes), leaving the z-axis for when they start building toward the sky.
InGodot, the “y is up” variation is used. However, it is possible that other software uses the “z is up” strategy, in which case you will run into
problems when importing your models. More on that later.
111111111
22222222NOTE
Axes Are Color Coded
Throughout all of Godot and most other 3D software, the three axes are color coded exactly the same way: the x-axis is red, the y-axis is green,
and the z-axis is blue.
The Metric System
In 2D, everything was measured in pixels. In 3D, we can’t do the same thing. When we place the camera differently, the size of objects and the
distance from the camera changes. In fact, we might even use a split screen in which each camera only uses half the screen width. This means
using a fixed pixel unit doesn’t work in 3D.
Instead, the metric system is used. When you set a node’s translation to, say, (50, 50, 0), it moves 50 meters to the right and 50 meters up
within the scene.
All professional 3D-modeling software uses this convention, so if you ensure that objects are the right size in your software, they should look
perfect once imported to Godot.
Models, Meshes, and Primitives
If you look in your 3D editor, you don’t see anything, because the
Spatial node has no geometry attached to it. It’s an empty node, just as
Node2D. In fact, all 3D nodes have no visual presence, except for meshes.
A mesh is nothing more than a collection of vertices (or dots), connected to each other to make edges (or lines), which are connected to get
faces (or surfaces). In the image below, you can see that a cube has eight vertices, 12 edges, and six faces (Figure 13.3).
FIGURE 13.3
How meshes are built. (Obviously, there’s also a backside to this cube, but it doesn’t show in a 2D image.)
A model is a collection of meshes that belong together. For example, a character might consist of multiple meshes—one for his head, and two
for both his arms.
A primitive is a “standard mesh,” such as a cube, sphere, pyramid, or cylinder.
In the next chapter, we’ll look at how to import 3D models into Godot.
NOTE
Dynamic Meshes
Sometimes, you’ll need to change meshes during the game or create new meshes on the fly. Godot offers the possibility to generate and
manipulate meshes using GDScript with the
ImmediateGeometry node, but it’s beyond the scope of this lesson.
Note that this is different from animating an object. Everything you’ve learned in Hour 10 about animation also applies to 3D, and you can
animate any object any way you want by keyframing the translation, rotation, or scale.
Importing Meshes and Models
In this chapter, I’ll assume you have 3D-modeling software installed on your computer, and that you know how to use it (at least a little). If not,
Blender is a professional, free modeling software that you can install and use. All you need to do—for now—is add a cube to your scene and
export it as an .obj file.
When it comes to importing, there are two options:
Importing a single mesh: This gives you more control, as you import each and every mesh yourself, but you lose textures and animation
(and other properties) associated with the mesh.
Importing a complete model/scene: This gives you less control, but it imports a complete scene with all its properties.
Importing a Mesh
As soon as you add an .obj file to the Godot project directory, it will be automatically imported. A scene in which your mesh resides will be
created. In the case of the simple cube, it looks like the one in Figure 13.4.
FIGURE 13.4
A scene containing the cube node. The cube is black because there is no light source, only a mesh.
If you’re not happy with the way your mesh was imported, you can select it in the FileSystem window and open the Import tab (next to Scene).
There, you can change settings and click “reimport” (Figure 13.5).
FIGURE 13.5
The reimport window. It also works if you select multiple files of the same type.
111111111
22222222One disadvantage is that the automatically created scene cannot be edited. You have two options to fix this:
If you double-click the scene to open it, it will warn you and give you the option to create a new inherited one.
Right-click an existing node (in a different scene), and choose
Merge fromScene. Locate the .obj scene, click the cube node, and
click “OK.”
As you might have noticed, the mesh of our 3D model is displayed by a
MeshInstance node. This is always the case—every single mesh
needs a single
MeshInstance node.
NOTE
MultiMeshes
The
MeshInstance is quick and powerful, but if you’re using hundreds or thousands of instances of the same mesh, it will severely affect
performance. For this, look at the
MultiMesh node as the solution.
Importing a Model/Scene
Importing a scene uses the same process, just a different file format. The file format to use is .DAE. Unfortunately, some software has a really
broken export system for this, which you must first fix:
Maya/3DS Max: uses “OpenCollada” plugins.
Blender: On the Godot website, under downloads, you’ll find a “Better Collada Exporter.”
Once you have your scene exported, add it to the folder of your Godot project, and it will automatically import. Below is a scene with three
cubes. Notice in Figure 13.6 how Godot also imported the light, the camera, and an animation player.
FIGURE 13.6
A complete scene, imported automatically.
Note: A new standard asset exchange format called glTF has been released. It has significant advantages and will replace Collada in the near
future.
3D Editor
Now that we have something in our scene, let’s see how we can move around our 3D world and change the view.
First, it’s important to be in the 3D editor view. You can get to the 3D view by clicking the word “3D” at the top, pressing the F2 key, or selecting
any 3D node in the Scene view.
Moving the Camera
It’s very important to be able to move the camera around easily. It saves you a lot of time, and it allows you to quickly move around the scene
and look at objects from all angles. The default controls are as follows:
Zoom in/out: scroll wheel
Orbit around selection: middle mouse button + drag
Pan left/right/up/down: shift + middle mouse button + drag
If you don’t like these controls, you can change them to a different popular configuration in the editor settings (Figure 13.7).
FIGURE 13.7
The 3D editor settings. There are many properties you can change are not covered in this lesson.
Changing Camera View
By default, the editor camera is in perspective view (as can be seen in the top-right corner of the view). Sometimes, however, it’s more useful
to look at the world in 2D to see if things line up perfectly.
To do so, click on the “Perspective” text, which opens a window.
FIGURE 13.8
The camera view list. Every view is quite self-explanatory; the top view, for example, views the world as if the camera were watching it from
above. In this list, one can also turn on/off certain visuals within the editor.
Additionally, we can also split the screen into multiple views. To do so, click the “View” button to get the following dropdown list:
111111111
22222222FIGURE 13.9
You can split the screen into up to four viewports. It’s common to set the top-right viewport to perspective and the others to top, left and front.
This ensures that you can see the scene from all sides. You can also turn on/off the origin lines and the grid.
Transforming Nodes
You probably already noticed that, in 3D view, there are circles and arrows drawn around an object. These are called gizmos, and they can
help you translate, rotate, and scale the node quickly. They do not show up in the final game.
To use a particular gizmo, hover over it with your mouse until it turns white, then click and drag it.
Gizmos are nice, but sometimes they can be in the way, especially if you want to transform only one element (such as scale). To switch to a
singular transformation mode, use the buttons on the upper left.
Of course, if you know exactly how many units you want to translate/rotate/scale a node, you can simply edit the number in the properties of the
node in Inspector.
Cameras
We’ve thus far learned everything about placing objects in our scene and working within the 3D editor. However, if you only have 3D models in
your scene, you would see nothing when you started the game! Without a camera in the 3D world, there’s no way to show the world, because
the engine doesn’t know from which angle and distance to view the world.
FIGURE 13.10
Gizmos displayed around a cube.
FIGURE 13.11
From left to right: default setting, only translation, only rotation, only scaling.
Creating a Camera
To put a camera into the world, we use, not surprisingly, the
Camera node. Make sure you don’t accidentally choose the Camera2D
node.
The new camera will be instantiated at the origin, and you can move it around and rotate it using gizmos. To preview what the camera sees,
press the
Preview button at the top right of the editor view.
Camera Settings
Like every node, the camera has important properties that can be edited in Inspector.
FIGURE 13.12
The main camera settings.
The projection property has two options: perspective and orthogonal. The perspective type is the default type, with objects getting smaller as
they are further away. With orthogonal projection, sizes stay the same, and you basically convert a 3D world to a 2D one on the screen.
The fovy property stands for “field of view,” and determines how much the camera is zoomed in. What’s the difference with moving the camera
closer? By increasing the field of view, objects get “warped” around the edges of the screen, as if you’re applying a fisheye effect. On the other
hand, decreasing the field of view gradually turns a perspective camera into an orthogonal one.
The near and far properties determine how close and how far the camera can see. For example, if you have a camera following a player, you
might want to cut away all objects closer to the camera (than the player) to have an unobstructed view.
Lastly, we have the very important current property. To understand what it does, we must first learn about viewports.
About Viewports
Every camera must answer to a viewport. Look at it this way: The camera registers part of the world, then hands this picture over to the
viewport, which is responsible for actually displaying it on the screen.
The root node of every scene is automatically a viewport. Godot does this for you, so our current camera, a child of the root node, has a
viewport. Because it’s the only camera, everything works as expected.
If we added another camera as a child of the root node, we’d run into problems. A single viewport can only display the picture from a single
camera, so we have to choose. This is where the current property comes into play. By setting the current property on a
Camera node to
“on,” it becomes the active camera for its viewport.
Below is an example script that switches to a different camera when the game starts.
LISTING13.1 Camera Switching
111111111
22222222Click here to view code image
func _ready():
$Camera.set_current(false)
$CameraTwo.set_current(true)
Working with Multiple Cameras
There are cases, however, where you want to use multiple cameras at the same time; for example, in a split-screen game or when you want to
display a minimap. If that’s the case, you’ll need to add your own viewports for each camera.
This is discussed in great detail in Hour 21 (“Viewports and Canvas”).
Manipulating the Camera
Most likely, you won’t have a static camera. The camera will follow your main player, or, as often seen in strategy games, the player can freely
move the camera around the map.
The easiest way to make the camera follow the player is to make the
Camera node a child of your
MeshInstance node. However, this
is also very restrictive and results in jagged movement, as the camera follows exactly what your player is doing.
A better way is to control the camera with code. Here’s an example of how to make the camera follow a node called Cube from a safe
distance. (This script should be placed on the parent node of the camera and cube.)
LISTING13.2 (Very) Simple Camera Follow
Click here to view code image
extends Spatial
func _process(delta):
$Camera.set_translation($Cube.get_translation() + Vector3(0, 25, 25)) # offset
the camera from the cube
$Camera.set_rotation(Vector3(-45,0,0)) # rotate it so it faces the cube
As you can see, in 3D, we work with Vector3(X,Y,Z) instead of Vector2(X,Y). Also as expected, get_position() becomes
get_translation(), and all 3D functions accept Vector3 arguments only.
If you test this code, it will work, but it will still feel choppy. Luckily, Godot offers an alternative to the
Camera node, which is the
InterpolatedCamera node.
Interpolated Camera
The
InterpolatedCamera node is the same as a regular camera, but with a useful addition, which you can see in Inspector.
FIGURE 13.13
The extra properties for the interpolated camera.
You can set a target node, and it will smoothly follow the node wherever it goes. So if the node abruptly moves, the camera will interpolate
positions and slowly move with it (instead of jumping around).
There’s one important pitfall: the
InterpolatedCamera node moves to exactly the location of the target node, instead of following from a
distance. So it’s best to set a
Position3D node as the child of the cube, offset it by a certain distance and make it face the cube, then use
that
Position3D node as the target:
FIGURE 13.14
A working configuration for a smooth camera follow.
In the end, it depends on what kind of camera behavior you want. The
InterpolatedCamera node provides a quick and easy way to get a
smooth camera follow, but it’s highly likely that you’ll need something more advanced or unique. In that case, you can just use a
Camera
node and script the desired behavior yourself.
Summary
In this hour, you’ve learned about the spatial node, and how to recognize and use 3D nodes. You’ve learned how to import 3D models and
meshes into Godot and use them in a scene. You’ve learned how to navigate around the 3D world, and how to make the most of the 3D editor.
Finally, you’ve learned how to create and set up cameras, what to do with multiple cameras, and how to script camera behavior.
Q&A
Q. Can I use 2D nodes in a 3D game?
111111111
22222222A. Yes, 2D nodes can be used, and they will be fixed to the camera screen. Obviously, you can use all
Control nodes, which are 2D by
nature, for the GUI of your game. Other 2D nodes, such as the
TouchScreenButton, work exactly the same in 2D and 3D, and
should be used in both. But besides that, most 2D nodes should be replaced by a 3D counterpart or a GUI node. And some nodes simply
don’t do anything in 3D, such as the
Camera2D node.
Q. How do I detect what’s under my mouse in 3D?
A. In 2D, if you want to check if a Sprite was clicked, you can just use an Area2D and signals that check whether the area was entered or
exited.
As you might have guessed, it’s not so simple in 3D. Usually, raycasts are used, which are invisible lines shot from the camera toward the
3D world. These raycasts check whether the line is obstructed by any object. They are too complex to discuss here, but remember them,
as they are very useful.
Q. Help—my object doesn’t rotate the way I want it to!What do I do?
A. 3D rotation is a tough subject. If you rotate multiple axes at the same time in the wrong way, you could get something called “gimbal lock.”
It’s a transform configuration in which you suddenly lose a degree of freedom and can only rotate around two axes. Usually, people resort
to other rotation measures, such as quaternions or using the transform matrix that was covered earlier.
Workshop
Now that you have finished the hour, take a few moments to review and see if you can answer the following questions.
Quiz
1. Which three fundamental actions can you perform on any 3D node?
2. One can switch to the 3D editor by pressing the key.
3. Which axis points upward inGodot?
4. True or False: Importing inGodot happens automatically when you place a file in the project folder.
5. True or False: A .obj mesh can also contain other elements, such as lights and cameras.
6. True or False: You can only have a single camera per viewport in a 3D scene.
7. True or False: The
Camera node automatically smoothens movement.
8. Which data type should be used to contain 3D (X, Y, and Z) data?
Answers
1. Translate, rotate, and scale.
2. F2.
3. The y-axis.
4. True. You can, however, choose different settings and reimport if you want.
5. False. A mesh contains only a single 3D object, while a .dae scene contains everything.
6. False. You can have multiple cameras per viewpoint, though you need to choose which one you want to use by setting the current property.
7. False. You need to script that yourself or use an
InterpolatedCamera node.
8. The Vector3(X,Y,Z) data type.
Exercises
In this exercise, we will be creating a 3D “city” and writing a script that allows the camera to navigate it, just like in a city-building game.
1. Go to your favorite 3D-modeling software and create something that vaguely resembles a (small) city. Use cylinders, cubes, and
pyramids to create simple buildings.
2. Import your creation into Godot. Make sure you allow the individual buildings to be edited one way or another.
3. If not already in the scene, add a light so that you can see the city well.
4. Add a camera and point it toward the city. Attach a script to the camera so that it moves left/right/forward/backward when you press the
arrow keys on the keyboard. (Bonus points if you can make that movement smooth.)
5. Allow the camera to zoom in/out when the user scrolls his mouse scroll wheel.
6. BONUS: Create an animation for a building that makes it jump up and down. Start this animation when the camera gets within a certain
distance of this building.
7. BONUS (hard): Write a script so that every building within the vicinity of the camera starts jumping up and down. (I don’t recommend an
animation for this, but rather using code to make buildings jump.)
Bonus Exercise: We’ll be creating a very simple racing game.
111111111
222222221. Create a simple 3D mesh (such as a cube), and import it in to Godot. This will be a car.
2. Duplicate this mesh a few times and number each logically.
3. Attach a camera to each car and make sure each camera follows its own car.
4. Write a script that keeps track of which car you’re currently controlling. When you press a certain button (say, “K”), it should switch to the
next car.
5. In the same script, add an input handler. Write code so that the car you’re currently controlling (and _only _that car) responds to the arrow
keys for movement. For the best visual results, rotate the car in the right direction. (In such a simple environment with few reference
points, it can otherwise be hard to tell where your mesh is actually going.)
6. Now you should be able to control one car at a time and jump from car to car by pressing the “K” button.
111111111
22222222