Going forward in this series of Godot tutorials, we will often need to know when two objects come into contact with each other. In game development, this is known as collision detection. In this tutorial, we will learn how collisions work in Godot.
When a collision is detected, you typically want something to happen. For example, when the player sprite comes in contact with a wall, we want it to stop. Instead, if it moves over an object, we want it to be able to pick it up. This is known as collision response.
Godot offers four kinds of collision objects to provide both collision detection and response. Let’s try to understand how each one works and when to use them with practical examples.
KinematicBody2D nodes detect collisions with other bodies, but don’t automatically move according to physical properties such as gravity or friction. They must be moved manually by the user through scripts.
We have already seen an example in the Player movement tutorial, where we used KinematicBody2D to move the player.
When moving a kinematic body, you should not set its position directly. Instead, you must use the move_and_collide() or move_and_slide() methods. If after the movement the body has collided, as a response you may want your body to bounce, to slide along a wall or to alter the properties of the other body. The way you handle the collision response depends on the method used to move KinematicBody2D:
- When using move_and_collide(), the function returns a KinematicCollision2D object, which contains information about the collision and the colliding body. Any collision response must be coded manually using this information (KinematicCollision2D contains information about the colliding object, the remaining motion, the collision position, etc.)
- When using move_and_slide(), if the body collides with another one, it will slide along the other body rather than stop immediately. You don’t have to write any code to get this behaviour.
As mentioned above, we already have a KinematicBody2D object in our project, the Player node. So, let’s open the SimpleRPG project to complete its configuration.
If you remember, this node has a warning that we need to correct.
This warning is due to the lack of a collision shape. Collision shapes are used to define the body collision bounds and to detect contact with other objects.
The most common way to assign a shape to a collision object is by adding a CollisionShape2D or CollisionPolygon2D node as its child. These nodes allow you to draw the shape directly in the editor workspace.
Add a CollisionShape2D child node to Player.
In the Inspector, set Shape to New RectangleShape2D. Now, the sprite of the player will be overlaid with a rectangle that we can manipulate to set the size of the collision shape. Resize it to be the same size of our sprite.
As we learn the other types of colliders, we’ll see how they interact with our player’s KinematicBody2D.
StaticBody2D are bodies that take parts in collision detection but, as their name implies, do not move in response to collisions. They are mostly used for objects that are part of the environment like wall, tree, rocks, and so on.
To test StaticBody2D, first of all download the following image and import it in Godot (remember to turn off Filter in the Import panel).
Add a StaticBody2D node as a child of Root and rename it Rock. Then, add a Sprite node and a CollisionShape2D to Rock.
Select Rock‘s Sprite and drag the map_tiles.png file to the Texture property in the Inspector. The sprite will appear in the upper left corner of the game screen.
We do not want to use the whole image, but only a small region of it. To do this, in the Inspector find the Region section and enable it.
Now that Region is enabled, in the lower part of the editor you will see that there is a new panel called Texture Region. Open it.
There are various ways to select the region that interests us. In our case, all the elements are arranged in a 16×16 pixels grid, so the simplest solution is to set Snap Mode to Grid Snap, set the two Step values to 16px and then select the square that contains the rock.
Now select Rock‘s CollisionShape2D, set the Shape property to New CircleShape2D and, in the editor, resize the circle to cover just the rock.
Finally, select the Rock node and set its Position, in the Transform section, to (220, 90).
Now, if you launch the game and move the player, you will see that it will not be able to move through the rock!
If you notice, there is a small problem: when the player is near the rock, he is drawn under the grass. You can solve this problem by setting the player’s Z Index to 1 (the rock has Z Index 0 and will therefore be drawn behind). To do this, select Player and in the Inspector find the Z Index section under Node2D and set Z Index to 1.
RigidBody2D is the node that implements simulated 2D physics. You do not control it directly. Instead, you apply forces to it (gravity, impulses, etc.) and Godot’s physics engine calculates the resulting movement, including collisions with other bodies and collision responses, such as bouncing, rotating, etc. As in KinematicBody2D and in StaticBody2D, you must assign one or more shape to RigidBody2D.
To try it, add a RigidBody2D node as a child of Root and rename it MovingRock. Then, add a Sprite node and a CollisionShape2D to MovingRock.
Exactly with the same procedure we saw for StaticBody2D, set the Sprite texture and CollisionShape2D shape, then move MovingRock to Position (210, 30).
If you play the game now, you will see that MovingRock will start to fall down, hit Rock and begin to rotate as it continues its fall. You have just seen Godot’s physics engine in action for the first time!
You can modify RigidBody2D behavior setting its properties in the Inspector or through scripts. The body’s behavior is also affected by the world’s properties, as set in Project Settings → Physics.
Our game is a top-down RPG, so we don’t need gravity. With MovingRock selected, set the Gravity Scale value to 0 in the Inspector. Also in the Inspector, set Linear → Damp to 10 and Angular → Damp to 5 to add friction.
Run again the game. Now MovingRock doesn’t fall. You can use your player to push and rotate the rock!
Note that so far you have not entered any line of code!
The last type of Godot’s collision object is Area2D. It is an area that detects when other collision objects overlap, enter or exit from it. An Area2D node can also be used to override physics properties, such as gravity or damping, in a defined area. They also receive mouse and touchscreen input.
Add an Area2D node as a child of Root and rename it Flowers. Then, add a Sprite node and a CollisionShape2D to Flowers. Set the Sprite texture to use the flower image from map_tiles.png, and add to CollisionShape2D a rectangle shape covering the flowers (by now you should have learned how to do it!). Lastly, move Flowers to Position (140, 100).
Attach a new script to Flowers. We want to connect the enter signal of Area2D to this script to remove flowers from the game when the player move over them, as if the player had picked them up.
Select Flower and go to the Node panel. Here you will see a list of all the Area2D signals you can connect. Choose body_entered and press Connect…
In the window that opens, choose Flowers as the node to connect.
Press the Connect button. The Flowers.gd script will open and the method that will handle the signal will be added automatically. Write this code for the _on_Flowers_body_entered() method:
func _on_Flowers_body_entered(body): if body.name == "Player": get_tree().queue_delete(self)
This method checks if the body entered in the area is Player. If true, it will delete itself from the current nodes tree.
Run the game and try to move over the flowers.
In this tutorial we learned the foundations of the Godot’s physics engine, in particular all types of collision objects and their features. In the next tutorial, we will use this knowledge to create game maps with terrain that responds to collisions with the player.