
Implement object collisions for your 2D game
Tutorial
·
Beginner
·
+0XP
·
30 mins
·
Unity Technologies
In this tutorial, you’ll configure your player character and decorations so they collide.
By the end of the tutorial, you’ll be able to do the following:
- Implement collisions in your game using Rigidbody and Collider components.
- Troubleshoot game errors related to the physics system.
1. Overview
Now that you’ve created an environment for the game world that the player character will explore, you can start to set up different ways for the player to interact with that world. The first aspect of this is making the world feel a little more realistic by implementing some basic laws of physics in your game.
Physics in games refers to the properties of objects and how they respond to forces. Some games aim to simulate physics in a way that replicates the real world — for example, a game with the goal of replicating the experience of driving a racing car as accurately as possible. Other projects take a more flexible approach and implement rules of physics that deviate from the real world, such as unexpected behavior when objects collide or impossible leaps that the player character can make.
Note: For the purposes of this tutorial, we chose to use the Ruby’s Adventure asset set, and the images used in instructions will reflect this. If you chose another asset set, the file names will be the same, but in your corresponding theme folder.
2. Add a rigidbody component to the player character prefab
To simulate physics in your Unity project, you’ll use Unity’s built-in 2D physics system. Just as Unity provides a framework for creating games, the 2D physics engine acts as a framework that integrates with the game engine to implement physical behaviours, such as gravity, to your project. Unity only performs physics calculations for GameObjects that have a Rigidbody component attached, preventing unnecessary, resource-intensive calculations.
To make the player character GameObject a prefab and add a Rigidbody component, follow these instructions:
1. Turn the PlayerCharacter GameObject into a prefab.
2. Open the PlayerCharacter prefab in prefab editing mode.
3. In the Inspector window, select the Add Component button and search for and add the Rigidbody 2D component.
Important: You must select the 2D version of this component because your game is 2D.
4. In the prefab editing mode toolbar at the top of the Scene view, make sure that Auto-save is enabled.
5. To exit prefab editing mode, select Scenes in the breadcrumbs in the upper-left corner of the window, or select the arrow to the left side of the PlayerCharacter prefab.
6. Select the Play button to enter Play mode and test your changes.
Your character just slid down the screen and out of view — that needs to be fixed!
3. Disable gravity for the player character
The character slid down the screen because the Rigidbody 2D component is applying gravity to the PlayerCharacter GameObject. By default, gravity pulls a GameObject down the y-axis, so the PlayerCharacter GameObject was pulled down beyond the camera view of your scene. This default configuration won’t work for your game: your game has a top down view, which means everything is the ground, not just the bottom of the player’s screen.
To disable gravity for the PlayerCharacter GameObject, follow these instructions:
1. In the Hierarchy window, select the PlayerCharacter GameObject.
2. In the Inspector window, in the Rigidbody 2D component, set the Gravity Scale property to 0.
3. Save your changes.
Notice that a vertical blue line is now present next to the Gravity Scale property — this is because you’ve made changes to the prefab instance for the PlayerCharacter GameObject rather than the prefab asset itself.
This difference between an instance and the prefab asset is called an override, because changes to instances will always take precedence over the default configuration of the prefab asset. In this situation, you’ll never want the character to fall off the player’s screen, so you actually need to apply the override to the prefab asset itself.
4. In the GameObject header at the top of the Inspector window, open the Overrides dropdown.
The dropdown menu displays the Rigidbody 2D component you just made a change to.
5. Select Apply All.
6. Test your changes in Play mode.
The player character will now move as expected without falling off the screen.
4. Add a collider to the player character prefab
The Rigidbody 2D component gives the PlayerCharacter GameObject a physical body, allowing it to respond to forces and interact with Unity’s 2D physics system. However, there’s another component the PlayerCharacter GameObject needs to interact with other GameObjects: a 2D collider.
2D Colliders are defined using simple shapes, like squares or circles that approximate the shape of a GameObject. The physics system uses this shape to determine the GameObject’s physical boundaries and use it to perform physical calculations for interactions like collisions or trigger activations.
To add a 2D collider to the PlayerCharacter GameObject, follow these instructions:
1. Open the PlayerCharacter GameObject in prefab editing mode.
2. In the Inspector window, select the Add Component button and search for and add the Box Collider 2D component.
All the player character sprites for the 2D Adventure Game: Robot Repair course are roughly rectangular, so this collider is a good fit.
The Scene view will now show the PlayerCharacter GameObject sprite surrounded by a green box. This box is the shape of the collider and the shape of the PlayerCharacter GameObject that the physics system will use.
3. In the Inspector window, select the Edit Collider button.
The collider currently covers the entire character. However, because this game uses a top down perspective, this can cause interactions to feel off. For example, the player won’t be able to walk in front of an object because the collider will block it immediately.
4. In the Scene view, drag the collider handles to resize the collider and make its height cover only the lower part of the sprite—over the character’s hip.
5. Exit prefab editing mode.
5. Configure objects to collide with the player character
You’ve configured the PlayerCharacter GameObject to collide with other GameObjects, but at the moment there’s nothing for it to collide with in your game. In the previous tutorial, you added decorative GameObjects to the game — these will be perfect to test collisions.
To configure the decorative GameObjects for collision, follow these high-level instructions:
1. Choose one of the decorative GameObjects that you set up and open the prefab asset in prefab editing mode.
2. Add a Box Collider 2D component to the prefab.
Important: This decoration doesn’t need a Rigidbody 2D component because the forces of physics don’t need to affect it. The decoration does need a collider component so that GameObjects with Rigidbody 2D components can interact with it correctly.
3. For decorations, adjust the collider size to cover the following:
- The full width of the decoration sprite.
- Half the height of the sprite.
4. For DamageZone GameObjects and areas like water or obstacles that the PlayerCharacter GameObject shouldn’t enter, adjust the collider so it fully covers the sprite area to block player movement correctly.
5. Repeat these steps for the rest of the decoration GameObjects in your scene.
6. Save your changes.
7. Enter Play mode and test the game.
Try to get the player character to move around and through the decoration GameObject.
You might notice that although the PlayerCharacter GameObject now collides with the decorations, two new issues appeared: the PlayerCharacter GameObject starts to rotate oddly after a collision, and the movement can appear jittery when you keep colliding with a GameObject.
6. Fix the player character rotation
The PlayerCharacter GameObject currently rotates when colliding with a decoration GameObject because the physics system is attempting to simulate real world physics and apply different forces into it. In a 2D game, this shouldn't happen because these forces don’t exist.
To configure the PlayerCharacter GameObject to stop this from happening, follow these instruction:
1. Open the PlayerCharacter prefab.
2. In the Inspector window, locate the Rigidbody 2D component.
3. Use the foldout (triangle) to expand the Constraints section.

4. Enable the Freeze Rotation property to stop the Rigidbody2D component applying rotation forces to the PlayerCharacter GameObject.

5. Exit prefab editing mode and save your changes.
7. What is causing the jittering?
Now you need to address the remaining issue: the PlayerCharacter GameObject jittering.
Jittering happens because the physics system uses a simplified copy of the scene that only contains the colliders to make the physics calculations. This approach makes calculations simpler, but it also means that whenever a GameObject with a Rigidbody 2D component moves in the scene, the system needs to perform the following actions:
1. Move its copy of the GameObject in the simplified physics scene.
2. Apply forces and compute any collisions.
3. Move the GameObject in your scene to the new position calculated in the physics scene, which might be affected by the calculations that the system has completed.
What exactly is causing the jittering?
When you enter Play mode and make the PlayerCharacter GameObject collide with the decoration GameObjects with colliders attached, the following things happen:
1. The character’s movement gets updated during the frame update.
2. The physics system moves its copy of the PlayerCharacter GameObject to that new position.
3. The system finds that the PlayerCharacter GameObject’s collider is now inside the collider for the decoration GameObject.
4. The system moves its copy of the PlayerCharacter GameObject back outside the collider of the decoration GameObject.
5. The system synchronizes the PlayerCharacter GameObject in your scene with that new position.
When you were testing, you were constantly moving the PlayerCharacter GameObject inside the decoration GameObject’s collider and the physics system was moving it back out again. The conflict between the player input and the physics system’s standard behavior is what causes the jittering.
8. Fix the PlayerCharacter jittering
To fix this issue, you need to move the PlayerCharacter GameObject using its Rigidbody 2D component rather than its Transform component. This allows Unity’s physics system to synchronize the GameObject and Rigidbody positions more accurately, preventing the PlayerCharacter from entering colliders rather than the PlayerCharacter being pushed out afterward.
Physics computations need to occur at regular intervals to remain stable. Since Update() runs once per frame—and the frame rate can vary due to many factors—it’s not a reliable place for physics logic. Instead, move your physics-related code to an alternative function Unity offers: FixedUpdate, which runs at a fixed rate in sync with the physics engine.
However, avoid reading the player’s input (calling moveAction.ReadValue<Vector2>()) inside FixedUpdate(), because it may skip quick button presses. Instead, keep reading input values in Update(), where it’s checked every frame.
To modify your approach to player movement, follow these instructions:
1. Open the PlayerController script in your IDE.
2. Add the following line of code at the beginning of the PlayerController class, after the MoveAction declaration:
Rigidbody2D rigidbody2d;This instruction declares a new variable called rigidbody2d. This variable needs to be accessed within this script but not in the Unity Editor, so the declaration doesn’t include the public keyword.
3. Add the following line of code immediately below to declare the Vector2 variable move:
Vector2 move;4. In the Start function, beneath the instruction enabling the MoveAction, add the following line of code:
rigidbody2d = GetComponent<Rigidbody2D>();This instruction gets the reference for the Rigidbody component attached to the GameObject that this script is attached to — the PlayerCharacter GameObject.
5. In the Update function, remove the physics calculation instructions for the position and the Vector2 type for the move variable (because now you’ve declared its type at the beginning of the class).
The Update function should now look like this:
void Update()
{
move = MoveAction.ReadValue<Vector2>();
Debug.Log(move);
}6. Underneath the Update function, declare the FixedUpdate function:
void FixedUpdate()
{
}You’ll learn more about the details of creating a new function in a later unit of this course.
7. In the FixedUpdate function, add the following lines of code that contain the calculation to use the Rigidbody 2D component’s position values rather than the Transform component’s values:
Vector2 position = (Vector2)rigidbody2d.position + move * 3.0f * Time.deltaTime;
rigidbody2d.MovePosition(position);This approach to setting the player character’s position moves the PlayerCharacter GameObject based on the user’s input, but will stop that movement if the player character hits a GameObject that also has a collider. If you want to know more about this behavior, start with the Unity Scripting API documentation for MovePosition.
8. Save your changes and test the game in the Unity Editor.
The PlayerCharacter GameObject now collides correctly with decoration GameObjects, and, both the rotation and jittering issues have been resolved! In the next tutorial, you’ll define how the PlayerCharacter GameObject reacts to specific types of GameObjects it collides with.
9. More things to try
If you want to further develop your skills, explore new concepts, or improve your project, check out some of the optional activities below. Each one is tagged as either Easy, Medium, or Difficult, so you can choose the level of challenge.
These activities are entirely optional, so if you’re not interested, no problem — just skip this step. We do recommend attempting at least one of them in order to get the most out of this learning experience. Good luck!
Medium: Design a challenging path for the player character
In your game, there will be two elements that can damage the player character: the static damage zones you’ve already put in place, and patrolling enemy characters. Think about how you can arrange your environment and decorations so that the player has to engage with these obstacles before they can reach certain parts of the level.

10. Check your script
Take a moment to check that your script is correct before continuing.
PlayerController.cs
Important: If you completed any extension work in your script, this won't be reflected in the reference script below.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
public InputAction MoveAction;
Rigidbody2D rigidbody2d;
Vector2 move;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
MoveAction.Enable();
rigidbody2d = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
move = MoveAction.ReadValue<Vector2>();
Debug.Log(move);
}
void FixedUpdate()
{
Vector2 position = (Vector2)rigidbody2d.position + move * 3.0f * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
}
11. Next steps
You’ve started the work of integrating physics in your game world, but there’s still some more to do. In the next tutorial, you’ll set up tilemap collision so the PlayerCharacter GameObject can no longer walk on water tiles, which will make your game feel more realistic and help you to craft a more nuanced environment design.