Collision Not Working Checklist
There’s a lot of ways that collision might not work as expected. Here are some reasons I’ve found. They are somewhat sorted in order of how likely I think they are to occur. None of these reasons are specific to 2D or 3D.
General Checklist
- You are running the wrong scene.
- The Run Project (F5, the play button on the left of the other buttons) button only runs the main scene, which might not be the same thing as the scene you currently have open.
- Run Current Scene (F6, the clapperboard icon with the play symbol on it) will run the current scene you have open.
- The main scene can be changed in Project Settings or by right-clicking on the scene you want in the FileSystem.
- You didn’t add a collision shape.
- All
CollisionObjects
need at least oneCollisionShape
orCollisionPolygon
as a child in order to work with collision. CollisionShapes
need to have their shape property set in order to work with collision as well.CollisionPolygons
need to have a polygon drawn to work with collision as well.- The shape needs to be a direct child of the
CollisionObject
. There can’t be any other nodes in the hierarchy between them. - For
TileSets
, you need to add a physics layer in the Inspector and then draw the shapes in the paint tab in theTileSet
docker. Make sure to click on each tile to set the shape.
- All
- Your sprite isn’t in the same place as the collision shape.
- Since the visuals are separate nodes from
CollisionShapes/Polygons
, they have separate positions and might be misaligned.
- Since the visuals are separate nodes from
- Your
CollsionShape/Polygon
is disabled.- It will be gray in the editor if it’s disabled. You just need to turn
disabled
off on theCollisionShape/Polygon
.
- It will be gray in the editor if it’s disabled. You just need to turn
- You scaled the
CollisionObject
.- You should change the size of the
CollisionShape/Polygon
instead of changing the scale of any of the collision nodes.
- You should change the size of the
- Your collision layers and masks are wrong.
- A
CollisionObject
belongs to acollision_layer
and acollision_mask
is what theCollisionObject
is looking for collisions with. - For example, if an
Area2D
has Mask 1 enabled and aCharacterBody2D
with Layer 1 enters it, theArea2D
will detect theCharacterBody2D
. - If the
CharacterBody2D
’s layer 1 is disabled, and layer 2 is enabled, then theArea2D
will no longer detect theCharacterBody2D
, unless theArea2D
’s mask 2 is also enabled.
- A
- Your collision layers and masks are wrong in the scene you are testing.
- If you instantiate a scene inside another with the editor, and then you modify a property on the instance, then that property is no longer in sync with the original scene’s property.
- For example, if you change the collision layers on the instance first and then the original scene, the instance’s collision layers will not update to match the original scene.
- You can click the reset icon next to the property to sync the property.
- The
CollisionObjects
are not in the same canvas.- Those kinds of collisions are not currently supported in Godot.
- This includes
CanvasLayer
,ParallaxBackground
, andViewport
.
- A fast moving object goes through another object it shouldn’t.
- Tunneling might be fixed by enabling the
continuous_cd
property onRigidBodies
. - Another way is to use a
RayCast
in front of the object to see if it will pass through another object the next physics frame.
- Tunneling might be fixed by enabling the
- Changing one
CollisionShape
changes them all.- This is because those shapes are
Resources
, which are shared if you duplicated the node or copy/pasted the shape. - For nodes you are planning to instantiate with code, expand the Resource section in the shape and enable Local to Scene.
- For nodes you have already instantiated in the editor, right-click on the shape and select Make Unique.
- This is because those shapes are
- You spelled a function name wrong.
- It’s easy to forget the underscore (
_
) before_physics_process
. It won’t be called automatically if you don’t type it.
- It’s easy to forget the underscore (
- You didn’t call any movement functions.
- For
CharacterBodies
, you need to callmove_and_slide()
ormove_and_collide()
after changing the velocity in order to move the character.
- For
- You are multiplying by
delta
/ not multiplying bydelta
.delta
is the variable passed into_physics_process()
that is the time in seconds since the last frame. It’s most often less than 1.0 unless the game is running very slowly.- For
CharacterBodies
,velocity
already takes time into account, so there is no need to multiply it by delta when changing it directly. - However, acceleration is change in velocity over time, so you will need to multiply acceleration by
delta
when modifying thevelocity
. move_and_slide()
takes no parameters, so multiplying by delta is not possible. Butmove_and_collide()
expects avelocity
multiplied bydelta
.
- You didn’t connect the signal.
- Signals will not be automatically connected based on function names.
- If you connect a signal via the editor, then when you have the script and the scene the signal was connected in open at the same time, a green “connected” icon will appear to the left of the line number of the function you connected the signal to. It might take a couple of seconds to show up. If it’s not there, then you need to connect the signal.
- Alternately, you can connect signals through code. Make sure that the signal connects and doesn’t fail because the connecting object is null, and that you are connecting it to the right object.
- You disabled processing on the node.
- Somewhere you have the line
set_physics_process(false)
(or the same for the_process
function if you are using that instead).
- Somewhere you have the line
- The node is paused.
- If the
SceneTree
is paused and you haven’t changed any node’sprocess_mode
, then all nodes will be paused, and there is no way to unpause the game. - Setting the
process_mode
toPROCESS_MODE_DISABLED
will also pause the node.PROCESS_MODE_INHERIT
will also pause the node if it has a parent that is paused.
- If the
- You are looking for the wrong kind of
CollisionObject
.- Make sure that if you’re using the
on_body_entered
signal, the node you’re looking for is actually a body (and the same for areas).
- Make sure that if you’re using the
- Area is not set to
monitoring
.- It’s set to true by default, but you might have accidentally changed it.
- Camera is following a moving object.
- If the player doesn’t appear to move and there are no other objects in the scene to compare it to, and the camera is a child of the player and is following it, the player might actually be moving, but you can’t see it. Add something to the background to compare the player to!
- There’s an error that tells you what’s wrong.
- Check the debugger!
- Errors are in red and warnings are in yellow. Errors are more severe than warnings, but you should check the warnings too, since one of those might tell you what the issue is.
- You found a bug.
- You can report it on GitHub! Make sure to check if it’s been reported already, however.
Still Stuck?
If you couldn’t find the answer to your collision problem on this list, there are still steps you can take to debug your issue.
- Turn on debug collision shapes.
- Under “Debug” in the top menu bar, enable “Visible Collision Shapes”. This will allow you to see them when you run the game.
- Print out variables / add breakpoints.
- Use the
print()
function or click to the left of the line number to add a breakpoint (or typebreakpoint
). Breakpoints pause execution of the code, and allows you to advance step-by-step until you run into the error. - Seeing the actual values of the variables might give you insight into what’s wrong.
- Use the
- Restart the engine.
- Sometimes this works!
- Try to reproduce the issue on a new project.
- While you are trying to recreate it, you could figure out what the issue is.
Conclusion
Collisions are complicated, so don’t feel bad for not getting them perfect the first time!