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
C# (CSharp) UnityEngine Rigidbody2D.AddRelativeForce - 8 examples found. These are the top rated real world C# (CSharp) examples of UnityEngine.Rigidbody2D.AddRelativeForce extracted from open source projects. You can rate examples to help us improve the quality of examples. RigidBody2D will work fine for this. Enable the contact monitor as recommended in the docs. Note the qualifier: because this can require a huge amount of memory if many bodies are in the scene. You're not going to have many bodies in the scene of a flappy bird game. Gravity will happen automatically, and you can apply an impulse when the button.
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
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.
Rigidbody2d Godot
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
RigidBody2Dis 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!
Area2D
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.
Godot Rigid Body
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:
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.
Conclusions
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.
Did you enjoy this article? Then consider buying me a coffee! Your support will help me cover site expenses and pay writers to create new blog content.
Update (14 August 2020): Looking for an article on the Interpolate property on Unity Rigidbodies? We’ve put one together recently, so have a look here.
It isn’t particularly difficult to set up physics-based movement for objects in Unity — simply add a Rigidbody component onto an object that has a Collider component, and you’ll have yourself an object that moves and collides realistically with other objects.
If you start having fast-moving objects however, you might start to see these objects tunnel through obstacles.
The illusion of motion and tunnelling
Before we delve into why tunnelling occurs, it is important to understand this: the motion that we see in animated media is an illusion. Anything that appears to move on a screen does so because the screen is showing us a rapid sequence of images. This tricks our minds into thinking that there is motion, even though what we saw was a series of static images.
Similarly, the motion of the ball that we saw above was made of many individual images, each one showing the ball at different positions. How much a ball moves from one image to the next depends on how fast it is moving. Hence, a slower-moving ball moves very little from image to image, while a fast-moving ball can move a distance equal to several times its diameter from one image to another.
Because fast-moving objects cover so much distance from one frame to the next, it may skip over thinner objects (as pictured in the image above right) without registering a collision, since there is such a large gap between its positions in any two frames. This is what causes the tunnelling phenomenon you see.
The solution: Continuous collision
To address this problem, physics engines utilise a collision algorithm that projects a shape across an object’s path of travel. This shape is then used to check for any collisions from the object’s displacement between frames.
Rigidbody2d Addforce
This method of detecting collisions is called continuous collision detection, whereas the one that doesn’t prevent tunnelling is called discrete collision detection.
Discrete vs. Continuous collision
Although continuous collision detection is clearly the better choice, game engines generally do not enable continuous collision detection for all objects in their physics engines. This is for a simple reason: continuous collision detection is significantly more expensive, so having too many objects using it can unnecessarily use up computing power! Since only fast-moving objects suffer from the tunnelling problem, developers often enable continuous collision detection only for these objects.
In Unity, the option to turn on continuous collision detection can be found on the Rigidbody2D
and Rigidbody
components, which are used in 2D and 3D games respectively to give objects physics-based movement. Again, the idea here is to set the collision detection mode to Continuous for fast-moving objects, and leave the rest of the objects at the default value of Discrete.
Article continues after the advertisement:
Continuous Dynamic vs. Speculative
If you look at the Rigidbody
component, you will find that it has 2 additional values in Collision Detection compared to its Rigidbody2D
counterpart: Continuous Dynamic and Continuous Speculative. These additional collision detection modes are further optimisations, unique to Unity’s 3D physics system, and in place because 3D collision detection can be potentially much more expensive than its 2D counterpart.
Rigidbody
components that use the Continuous mode only use continuous collision detection on static objects (i.e. Collider
components without a Rigidbody
, which means the object does not move using Physics). This means that, in theory, tunnelling can still occur when you are colliding with any object using a Rigidbody
component.
Rigidbody2d Rotation
Objects using the Continuous Dynamic mode will not have these issues, as they will use continuous collision against all objects, except against Rigidbody
objects using Discrete collision detection.
Continuous Speculative is even better. It collides against everything — static and dynamic objects in all modes of collision; is computationally faster than the other 2 modes of continuous collision; and detects certain kinds of collisions caused by spinning objects that are missed by other modes of continuous collision.
However, because it speculates (i.e. predicts) collisions based on objects’ current motions, collisions that are detected can sometimes be inaccurate.
Making sense of everything
All of this can be pretty confusing, isn’t it? Here are some good rule of thumbs to help you decide which modes to use:
- If there are no fast-moving objects in your game, you can safely use Discrete collision detection for all your objects. An object can be considered to be fast-moving if it can travels a distance larger than its width or height within a frame.
- If you don’t care about collision accuracy in your game,Continuous Speculative will be the way to go with your fast-moving objects. The rest of the objects in the game can use Discrete.
- For dynamic objects (i.e. objects with
Rigidbody
) that don’t touch fast-moving objects at all, you can safely use Discrete collision. - For dynamic objects that are not fast-moving, use Continuous collision on them if you need them to always collide with fast-moving objects.
- For dynamic objects that are fast-moving, always use Continuous Dynamic collision.
As a summary to help make sense of all the information above, here is a table that outlines how each of the collision modes interact with one another:
Article continues after the advertisement: