What You’ll Learn in This Hour:
Creating bodies that interact with each other
Understanding the different types of bodies
Using areas to detect presence and alter gravity
Making use of the navigation tools
This hour will guide you throughGodot’s physics system. You’ll learn how to create entities that interact with each other, respect gravity, and
behave like real physical objects. You’ll see how to make special areas that can detect the presence of objects and change the gravity in the
section. Finally, you’ll see how to use the navigation system to make entities walk around the game while avoiding obstacles.
Bodies and Shapes
Godot physics is primarily based on bodies and shapes. Bodies represent the physical entities that interact with one another, and shapes
describe the space they occupy. By creating bodies and assigning shapes to them, you can tell objects how to behave in the game.
Physics Bodies
As will be seen in detail later (see Table 8.1), there are different types of physics bodies. They have 2D and 3D variants that behave alike,
which makes the transition between them quite easy. Usually, the body is the root of the game object, since the physics engine can move the
children together because of the inherited transform.
TABLE 8.1 Types of Physics Bodies
Type
Description
Static
An object that does not move in the game but interacts with other objects.
Rigid
An object that interacts with the physics engine and is affected by it.
Kinematic
Objects that aren’t affected directly by physics but need to move and detect collisions.
Vehicle (3D only)
Road-traveling vehicles.
Collision Shapes
Collision shapes define the area of the object inside the physics engine. This ensures flexibility to define a hitbox that doesn’t exactly match the
shape of the visible object. It makes it possible, for instance, to make a hidden passage that looks like a wall, or to have a complex shape for
the visible entity while keeping a simple shape on the physics side for better performance.
TIP
Shape Visibility
By default, collision shapes are only visible inside the editor. If you need to show them in-game to help you debug something, you can enable
the Visible Collision Shapes option in the Debug menu (see Figure 8.1). This option affects the project in the editor, but won’t be enabled in
the exported game.
FIGURE 8.1
Debug menu. You can enable a few debugging features to help you find problems in the game.
To define a collision shape, you need to create a
CollisionShape or a
CollisionShape2D node, depending on the type of game you
are creating. This node must be a direct child to a physics body node. Then you need to set up the Shape property using the inspector. There
are different types of shapes you can create in 2D and 3D. You should pick one that best suits the interaction you are expecting. Consult the
engine documentation to learn about the various types of shapes.
In general, you don’t need to be pixel perfect when defining collision shapes. Simpler shapes are better for performance, and likely won’t be
noticed by the final player. For instance, a
CapsuleShape works great for characters, both in 2D and 3D. It is also possible to use
multiple collision nodes for a single body, which makes Godot use the union of the shapes.
NOTE
Transforming Collision Shapes
Changing the dimensions and extents of collision shapes is quite natural, but you should be careful when changing the scale property. Negative
and non-uniform scaling tend to cause issues with the physics, and the shapes don’t respond as they should. You should avoid this kind of
scaling, and instead change the parameters of the shapes themselves to adjust their size.
111111111
22222222Meshes and Polygons
Simple shapes are great for performance, but sometimes they aren’t good enough. For better fine-tuning of hitboxes, Godot provides the
CollisionPolygon and
CollisionPolygon2D. These nodes enable the ability to draw custom polygons using the editor tools.
For 3D, Godot has a tool to create collision shapes based on a mesh. Simply select the
MeshInstance node with the desired shape,
select the
Mesh menu on the toolbar, and click on the desired option. You can create a trimesh for concave structures or a convex shape
for a simpler mesh. It’s also possible to create a navigation mesh from this menu.
TRY IT YOURSELF
Making a Polygon Shape
Follow these steps to draw your own polygonal collision shape (see Figure 8.2):
FIGURE 8.2
A polygonal collision shape. The colored areas show the convex decomposition of the shape.
1. Create a new scene and add a
Node2D as the root.
2. Add a
RigidBody2D.
3. Create a
CollisionPolygon2D as a child of the RigidBody2D.
4. Click on the
Create Polygon tool.
5. Click a few times to add points to your polygon.
6. Once you’re done, you can click on the first point to close the polygon, or right-click to make it auto-close.
7. Select the
Edit Polygon tool.
8. Move the points around to change the polygon shape. You can hold the Ctrl key while clicking on a segment to add a new
point. To delete a point, just click it with the right mouse button.
9. Change the polygon until you’re satisfied. There’s nothing else that needs to be done; your polygon is ready.
TIP
Disabling Shapes
Godot offers you the ability to disable collision shapes. You can do that by checking the Disabled property of the shape in the inspector.
Disabling shapes can be useful for changing the hitbox when the character pose changes (like ducking). Instead of transforming the shape with
animation, you can enable some shapes and disable others. It can also be useful for testing; you can have multiple shapes on the node during
the development process, but not all of them are being used.
One-Way Collision
An interesting property of collision shapes is the One-Way Collision option (FIgure 8.3). It is very useful in platform games, as you can create
floating platforms that the player character can both stand on and jump through from a lower platform.
This effect is enabled by checking the property in the inspector. If you need some other direction, just rotate the shape. The Godot official
platformer demo makes use of this property, so you can check it if you need a reference.
FIGURE 8.3
The one-way collision indication on a platform. You can see this in the official Godot platformer demo.
Types of Physics Bodies
As stated earlier, Godot has a few different types of bodies. Each has a specific function and acts in a certain way. Choosing the right type for
the action you want can be tricky sometimes, but Godot makes it very easy to change the type of node if needed. Since 2D and 3D types are
very much alike, they will be grouped together.
Static Body
This is the go-to body type for non-moving shapes. However, some moving structures might be better represented as
StaticBodies, such
as moving platforms and the pad of a breakout game. In general, a static body should be used if the object should act like a stop for other
bodies but not be moved itself by the physics engine.
Static bodies do not increase the processor usage, since they don’t need to actively check for collisions (instead, the moving bodies will make
such checks). This means you can add many of them without worrying too much about performance (see Table 8.2).
111111111
22222222TABLE 8.2 Static Body Properties
Property
Description
Friction
The amount of friction on the body’s surface, on a scale from 0 to 1.
Bounce
How much other objects will bounce when coming in contact with the body.
Constant Linear Velocity Simulates a motion for the body, which affects how other objects interact with it. This does not make the body move.
Constant Angular VelocitySimulates a rotation of the body, affecting other physics objects that touch it.
Rigid Body
On the other hand, if you want an object to be fully controlled by the physics engine,
RigidBody is a good choice. This type of body has a
mass, respects gravity and inertia, and can be pushed by other objects. It is generally used to simulate real-world physics.
Rigid bodies keep a linear, angular velocity. This means they’ll keep moving in a certain direction and maintain their momentum. They’ll also
rotate when affected by other forces and keep rotating unless stopped by friction or another force (see Table 8.3).
TABLE 8.3 Rigid Body Properties
Property
Description
Mode
How the body will behave. “Rigid” is the default mode, as it is fully integrated with physics. “Static” mode does not move at
all, “character” avoids rotation, and “kinematic” acts like a kinematic body.
Mass and Weight Dictates how the body will interact with gravity and how much force it will have upon other objects.
Gravity Scale
How much the body will be affected by gravity.
Custom IntegratorDisables the internal integrator. With the exception of collisions, only your code on integrate_forces() will move the
object.
Continuous CD
Enables the continuous collision detection. Fast objects, such as ones that would pass beyond the wall in a single frame, will
be detected. The 2D version also has options to use “ray” or “shape” for this kind of detection.
Contact
Monitor/Reporting
If contact monitoring is enabled, the body will emit signals when it detects a collision. The “contacts reported” property
dictates how many object contacts will be detected at once.
Sleeping/Can
Sleep
A body that does not move for some time will “sleep,” i.e., it won’t actively detect collisions, but will awaken if it comes into
collision with another object. This property can stop that behavior.
Axis Lock (3D
only)
Fixes the rotation of the body caused from other forces to a single axis.
NOTE
Rigid versus Soft Body
The concept of a rigid body contrasts with that of a soft body. A soft body can be deformed by physics (just like a basketball will deform when
contacting the ground). Usually, such effects pass unnoticed if the material is elastic, so the use of rigid bodies is more efficient. Godot’s
engine does not support soft bodies, but, as it’s still evolving, it very likely will soon.
Custom Integrator
One of the special capabilities of RigidBody is the custom integrator function. This allows you to complement or even replace the way the body
moves, and can be useful for advanced and custom physics properties.
This is achieved by overriding the _integrate_forces() method in a script. The method receives a Physics2DDirectBodyState
object, which can be used to probe and change the forces acting on the body.
TIP
Applying Impulses
RigidBody has a method called apply_impulse(). With it, you can shift the body as if some thrust were applied, making it change
movement based on its mass and shape. You can imagine it as a bat hitting a baseball or a cue pushing a billiard ball.
Kinematic Body
This is a special type of physics body. A
KinematicBody can detect collisions and be moved via code, but isn’t affect by other objects. It
won’t fall because of gravity or move around when hit by another object. This property makes it very useful for platformer characters that
respect their own laws of physics.
While a dynamic character (i.e., one implemented with
RigidBody) is more seamlessly integrated with the physics engine, it’s hard to
predict its movement. A kinematic character is guaranteed to go from one non-colliding state to another, so it is more easily controlled via
code.
TIP
Platformer Demo
Godot provides a collection of demo projects to show off many of its features. There are both 2D and 3D platformer game demos that makes
use of the
KinematicBody functionality in addition to a 2D demo with a dynamic character. While the demos are not extensively
documented, they are quite simple, and can serve as a reference. Make sure to check them if you have doubts.
111111111
22222222Moving a Kinematic Body
Since this type of body does not move on its own, it’s necessary to use scripting to achieve movement. Most of the time, you’ll make use of the
move_and_slide() method. This changes the object’s position while respecting collisions and surface sliding, so movement is fluid and
the object doesn’t stick to walls or floors. You just need to feed the movement vector, and the body will follow it. Note that this is the speed, in
units per second, that the object moves (for 2D, the unit is pixels). Therefore, you should not multiply by delta to calculate the change in
position, since it’s done by the method itself. This method receives other optional parameters as well, so check the engine documentation to
learn what they can do. The following listing (Listing 8.1) shows an example of a
KinematicBody2D movement function.
LISTING8.1 KinematicBody2D Movement Example
Click here to view code image
extends KinematicBody2D
# The speed in pixels per second
export (float) var speed = 100.0
# Run this function in a synchrony with physics processing
func _physics_process(delta):
# Calculate the direction vector based on input
var direction = Vector2()
if Input.is_action_pressed(“ui_left”):
direction.x = -1
elif Input.is_action_pressed(“ui_right”):
direction.x = 1
if Input.is_action_pressed(“ui_up”):
direction.y = -1
elif Input.is_action_pressed(“ui_down”):
direction.y = 1
# Normalize the movement vector and modulate by the speed
var movement = direction.normalized() speed
# Move the body based on the calculated speed and direction
move_and_slide(movement)
This script can be applied directly to a
*KinematicBody2D node. It checks the input to fill a direction vector. This vector is normalized
to make it unit length and avoid faster movement in diagonals. When multiplied by speed, it makes a vector pointing in the same direction, but
with speed as magnitude. Then we feed the result to the move_and
s
lide() function, making the body move while checking collisions and
avoiding getting stuck to surfaces.
TIP
Collision Layers and Masks
Sometimes, you need to avoid certain types of collisions (e.g., avoiding bullets shot by enemies colliding into the enemies themselves). While
it’s possible to set exceptions, it may be a daunting task to set every pair. This is where layers and masks come into play.
A collision layer is a property of the collision object (body or area) that states the object type. You can set up names for the layers in Project
Settings to help in this categorization. The collision mask states the type of object with which the body will collide. These are defined as flags,
so any object can be in multiple layers and have multiple masks.
If you have object A on layer 1 with mask 2, it will not collide with objects of its own category, but will collide with all other objects on layer 2. If
object B is on layer 3 with mask 1 and 2, it’ll also collide with object A and objects on layer 2, but not with itself.
This is a topic that confuses a lot of Godot users, but it’s easier if you imagine layers as categories or types of objects, and masks as collision
targets.
Areas and Presence Detection
Besides physical movement simulation, sometimes you need to detect the presence of an object in a place, be it to activate a trap, trigger a
cutscene, or engage a teleportation. Godot provides the
Area and
Area2D nodes to make this process easier.
These nodes are also responsible for enabling area effects, such as a gravity override (as we’ll see later in this chapter), and audio alteration
(as will be presented in Hour 19).
Area Monitoring
The
Area node has a monitoring property that is enabled by default. This property is responsible for detecting the presence of bodies and
other areas inside the area. If it gets disabled, it will stop reporting overlaps and won’t send signals.
There are eight signals responsible for warning when other objects enter or exit the area. Some are for bodies, others are for area overlaps.
You can use these to detect and trigger an action when the objects start or stop overlapping.
You can also use the get_overlapping_areas() and get_overlapping_bodies() methods to list all the current overlapping
objects. This can be useful if the action is triggered by a button press when in the area, not when the overlap starts. Both methods need the
monitoring property enabled. Other areas must have the monitorable property enabled to be detected.
111111111
22222222Gravity Override
Another interesting function of Areas is the ability to change the gravity in a certain location. This can be enabled by changing the Space
Override property. It has a few possible values, but essentially, it can be summed up with “replace” and “combine”.
Replacing will ignore all areas with a lower priority (as defined in another property) and simply replace the gravity by its current values.
Combining will add the effects to the areas already calculated, following the priority order.
NOTE
Linear and Angular Damping
Areas can also replace/combine the linear and angular damping properties. These properties dictate how much the area will lessen the linear
and angular momentum of the bodies passing through it. This also depends on the Space Override property being turned on.
Rigid bodies have similar damping properties, but the properties only affect the bodies themselves, like when air resistance is applied to an
object.
Ray Casting
The idea of ray casting is creating a line—for example, shooting a limited-range laser and seeing if it hits something. This can also be used to
check the line of sight. Though usually limited to a line, it’s also possible to cast custom shapes, so you can use a cone for sight detection
instead of a simple line.
There are mainly two ways to cast rays inGodot: by using the
RayCast or
RayCast2D nodes, or by calling the physics server directly
in the code. The first method is great for simple casting, since it can be seen in editor and can be checked anytime. The other method is more
advanced but also more flexible, and is easier for instant ad hoc ray casting, as well as shape casting.
RayCast Nodes
RayCast and
RayCast2D (see FIgure 8.4) are very simple nodes. They simply cast a ray in the appointed direction and return the
result every frame. You can make use of them by calling the is_colliding() and get_collider() methods, besides the other query
methods.
FIGURE 8.4
RayCast2D node as shown inGodot Editor.
TIP
Collision Exceptions
Like every other collision object, it’s possible to set up exceptions to ray-casting effects so that if the ray hits a target marked as an exception,
it will ignore it and look for the next.
This makes it easier to use the ray-casting nodes, because you don’t need to worry about where the ray starts. For instance, if you’re using it to
determine the line of sight for a character, you can add the character body as an exception so the ray doesn’t collide with it, allowing you to
overlap them in Editor without issues.
Exceptions can only be added via scripting (by calling the add_exception() method), so you need some script attached to use this
functionality.
Ray Casting via Scripting
A more complex but flexible setup uses scripts to cast a ray (or shape) and directly query its results. This involves accessing the space state.
The basic way of doing this is to access the world from the object:
Click here to view code image
# For 2D
var space_state = get_world_2d().get_direct_space_state()
# For 3D
var space_state = get_world().get_direct_space_state()
This returns a Physics2DDirectSpaceState object, which can cast rays and shapes, among other capabilities. With it, you can use the
intersect_ray() method to ray cast.
The intersect_ray() method receives a few arguments, but the most important are the first and second, which are mandatory. They set
the start and end of the ray shape using the global space. The result of the method is a dictionary containing the collision data. If the result is
empty, it means no collision happened. The returned dictionary structure is described in Table 8.4.
TABLE 8.4 Resultant Dictionary froman Intersect Ray Query
Key
Description
position
The global–space position where the collision happened.
normal
The normal of the plane where the ray collided.
shape
Index of the shape of the body with which it collided.
metadata
Metadata of the collided shape. This is not the regular object metadata, but the one set with the physics server methods.
111111111
22222222collider_id ID of the object that stopped the ray.
collider
The collided object itself.
rid
The RID of the collided object. This special type of object can be used as a reference to the object when dealing with the
physics server directly.
Navigation and Path Finding
An interesting characteristic of some game types is the ability for movement of NPCs and other computer-controlled entities. It is used quite a
lot in RPG and RTS games, and can be used for racing games too. This section will show how to use Godot tools to make precompiled
movements and find dynamic paths in the game world.
Following Predefined Paths
A couple of nodes can be joined to make an object follow a predefined path (see Figure 8.5):
Path and
PathFollow (along with their
2D counterparts,
Path2D and
PathFollow2D). With them, you can draw a path in Editor and make it change the transform of the child
nodes.
FIGURE 8.5
The Godot icon following a drawn path.
The
Path node is responsible in making the path itself. When selected, it shows a set of tools with which you can draw the curve inside
Editor. This is a Bezier curve, and can be open or closed; you just need to set up the points and adjust their curvature with the pivots.
To make something go along the path, you need the
PathFollow node, which must be a direct child of a
Path node. This makes all
the direct children conform to the path by changing their translations and rotations (see Table 8.5).
TABLE 8.5 PathFollow Properties
Property
Description
Offset
Offsets, in an absolute number, the child object in the path.
Unit Offset Does the same as Offset, but considers a scale from 0 to 1.
H/V Offset Changes the offset in relation to the path on the horizontal and vertical axes, respectively.
Rotation
Mode
Selects the axes on which the node can be rotated when following the path. For 2D, you can only enable or disable the rotation.
Cubic Interp Enables cubic interpolation when calculating the route between the points. If disabled, a linear interpolation is used.
Loop
Makes the excess value in offset act as a return to the beginning of the path.
Lookahead Determines how many units the player can look ahead when interpolating the path. A greater value increases the accuracy but
decreases the performance.
Basic Path Finding
You won’t always know the exact trajectory beforehand. In an open-world game, you need to calculate the actual path during runtime, because
the start and end points change all the time. Godot has the
Navigation and
Navigation2D nodes to help with this task.
To make use of this functionality, you need first to add a
Navigation node. It has no restriction as to where it is on the tree, since it doesn’t
do more than provide the special path-finding methods. Then you need a
NavigationMeshInstance (or
NavigationPolygonInstance for 2D) as a direct child. This node is responsible for providing the navigable areas in the world. After this is set
up, you need to call the methods from the
Navigation node to calculate paths when needed and apply the translation to the moving
objects. Note that Physics Bodies in the scene won’t act as obstacles, so you need to craft your polygons and meshes in a way that they don’t
overlap with the places where a path isn’t possible.
TIP
Generating Navigation Meshes
While the Godot editor makes it easy to draw navigation polygons for 2D, it does not provide a way to edit a 3D navigation mesh, since this
would require advanced modeling functions. Instead, the easiest way to make this is to import from your 3D modeling software.
You can generate a
NavigationMeshInstance from a
MeshInstance quite easily. Just select MeshInstance and click on “Create
Navigation Mesh” from the toolbar on the
Mesh menu. Then move the resulting node to be a child of a
Navigation.
TRY IT YOURSELF
Simple Path Finding
Let’s create a simple 2D scene to test the path-finding functions:
1. Create a new scene and add a
Node2D as the root.
111111111
222222222. Add a
Navigation2D.
3. Create a
NavigationPolygonInstance as a child of the Navigation2D.
4. Using the inspector, assign a new
NavigationPolygon to the Navpoly property.
5. Click on the
Create Polygon tool.
6. Click around to create a general outline for our map. This is very similar to how we created collision polygons in the last
exercise. Click on the initial point again to close the polygon.
7. Click again on the
Create Polygon tool.
8. Make a polygon inside the main one to create holes. Those will serve as walls in our map.
9. Repeat steps 7 and 8 to make multiple holes.
10. Add a script to the
Navigation2D node with the following code:
Click here to view code image
extends Navigation2D
var start_point = Vector2()
var end_point = Vector2()
var path = []
func _input(event):
if event is InputEventMouseButton and event.pressed:
if event.button_index == BUTTON_LEFT:
start_point = event.position
elif event.button_index == BUTTON_RIGHT:
end_point = event.position
func _process(delta):
path = get_simple_path(start_point, end_point, false)
update()
func _draw():
for point in path:
draw_circle(point, 10, Color(1, 1, 1))
draw_polyline(path, Color(1, 0, 0), 3.0, true)
11. Enable the Visible Navigation option in the Debug menu. This will let you see the polygon in the running game.
12. Run the scene. Left-click to define the starting point and right-click to set the ending point. A line will be drawn with the path, with
circles marking the calculated points (see Figure 8.6).
FIGURE 8.6
Running this exercise. The white circles show the path points, while the red line follows the path.
NOTE
A* (A-STAR)
A common algorithm used to solve paths within a graph of predefined points and connections is the A (pronounced “a star”). It is widely used
in games, especially in those that rely on a grid for movement, such as RTS and tactical RPGs. While it would be possible to write the
algorithm with a script, Godot provides a dedicated class to help you leverage this path-finding tool with the native code performance of the
engine core.
For details on how to use this functionality, consult the engine reference for the AStar class.
Summary
In this hour, you saw a major overview of the Godot physics engine. You learned about possible collision shapes, then got a description of the
basic types of bodies available. You learned how to cast rays via nodes and via scripting. Finally, you learned the custom navigation and path-
finding tools offered byGodot Engine.
Q&A
Q. Why isn’t Continuous Collision Detection (CD) always on?
A. While Continuous CD can increase accuracy, it also degrades performance. It should only be turned on for fast-moving objects.
Q. Why do rigid bodies sleep?
A. When a body comes to a total rest, it’s unlikely that it will hit anything, unless the world is changed by forces other than physics. Since it will
move only if hit by something else, the other object will detect the collision and wake the rigid body. A sleeping body does not use
computer resources, so you can have a scene with lots of objects and have it run better if most objects are sleeping.
111111111
22222222Q. What’s the main difference between a rigid body and a kinematic body?
A. A rigid body will be moved by the physics engine, i.e., it will be pushed by other objects hitting it and by gravity. A kinematic body will stay
in place no matter how many objects hit it, and will only be moved by scripting.
Workshop
Try to answer the following questions to better memorize the contents of this hour.
Quiz
1. What are the main three types of bodies?
2. True or False: Collision shape nodes must be a direct child of the body.
3. True or False: It’s OK to scale collision shapes.
4. How can you override the gravity of a certain spot in space?
5. Is it possible to make an object repeat the same predefined path indefinitely?
Answers
1.
KinematicBody,
StaticBody, and
RigidBody.
2. True. The
CollsionShape must be a direct child to assign a shape to the body.
3. False. Non-uniform scales can cause inaccuracies in the physics engine.
4. You can use the
Area node with the Space Override property turned on.
5. Yes. The
PathFollow node has a loop property that can be used for this purpose.
Exercises
Try to reproduce this scene to get an experience of the Godot physics engine.
1. Create a new scene and add a
Node2D as the root. Save the scene.
2. Make a
StaticBody2D. Add a rectangular collision shape and move it to the bottom of the scene, like a floor.
3. Add a
RigidBody2D as a child to the root. Make a circular collision shape and position it over the floor.
4. Make sure to enable visible collision shapes in the debug menu.
5. Save the scene and play it. Observe the circular body falling to the floor.
6. Duplicate the
RigidBody2D four times and stack them in Editor, like in Figure 8.7:
FIGURE 8.7
A stack of circular rigid bodies. This is a way to see how they interact when falling over each other.
7. Play the scene again to notice the movement of the balls.
8. Add a
KinematicBody2D to the scene. Make a capsule shape for it.
9. Create a script for the
KinematicBody2D and paste the code from Listing 8.1.
10. Play the scene. Use the arrow keys of your keyboard to move the capsule. Note how it moves and interacts with the other bodies.
11. Move the bodies in the scene around and test different configurations. Check the
*KinematicBody2D and change the speed in
Inspector. See how everything behaves.