Your 2D player walks straight through an enemy, a coin won’t collect, or a bullet passes through a wall, and OnCollisionEnter2D or OnTriggerEnter2D never fires. Unity 2D collision not working is one of the most common beginner problems, and it nearly always comes from a short list of setup mistakes. This guide goes through them in order of how often they cause trouble, with a quick check for each.
The Rules for 2D Collision Events
For two objects to collide or trigger in 2D, all of these must be true:
- Both objects have a 2D collider (BoxCollider2D, CircleCollider2D, CapsuleCollider2D, PolygonCollider2D, TilemapCollider2D and so on).
- At least one of them has a Rigidbody2D.
- For collision events, the Rigidbody2D setups must be a pair that generates contacts (more on body types below).
- Their layers are allowed to collide in the Physics 2D settings.
- The script with the event method is on one of the two objects (or on the Rigidbody2D’s GameObject, which receives events for child colliders).
- The method name and parameter type are spelled exactly right.
Keep this list handy. Each section below is one of these rules being broken.
Mixing 2D and 3D Components
Unity’s 2D physics (Box2D) and 3D physics (PhysX) are separate worlds. A BoxCollider never touches a BoxCollider2D, and a Rigidbody ignores 2D colliders. Nothing warns you.
Check every object involved: components must end in 2D. A quick tell: if an object has a 3D collider, its gizmo is a 3D wireframe box rather than a flat green outline. This also applies to raycasts: use Physics2D.Raycast in 2D games, not Physics.Raycast.
Wrong Method Name or Signature
Unity calls these methods by name. A typo compiles fine and just never runs. The correct signatures are:
void OnCollisionEnter2D(Collision2D collision) { }
void OnCollisionStay2D(Collision2D collision) { }
void OnCollisionExit2D(Collision2D collision) { }
void OnTriggerEnter2D(Collider2D other) { }
void OnTriggerStay2D(Collider2D other) { }
void OnTriggerExit2D(Collider2D other) { }
Common mistakes:
OnCollisionEnter2D(Collider2D c): collision methods take Collision2D, not Collider2D.OnTriggerEnter2D(Collision2D c): trigger methods take Collider2D.OnTriggerEnter2dorOnTriggerEnter(missing 2D).
Add Debug.Log("hit " + other.name); as the first line to prove whether the method runs at all.
Missing or Wrong Rigidbody2D
Two static colliders never generate events. At least one object must have a Rigidbody2D. Then the Body Type matters:
- Dynamic: affected by gravity and forces. Collides with everything. Use for players, enemies, physics objects.
- Kinematic: moved only by your code. By default it doesn’t generate collision contacts with other Kinematic or Static bodies. It does with Dynamic ones. Triggers still work with Kinematic.
- Static: never moves. Only collides with Dynamic bodies.
So a Kinematic player walking into a static wall gets no OnCollisionEnter2D. Options: make the player Dynamic, or tick Use Full Kinematic Contacts on the Kinematic Rigidbody2D, or detect walls yourself with casts. Note that Kinematic bodies are never pushed back by walls even when they report contacts, which is why most 2D platformer players are Dynamic. The 2D platformer movement guide uses a Dynamic body for that reason.
Also check the Rigidbody2D’s Simulated box is ticked. Unticked, the body and its colliders are removed from physics entirely.
Trigger vs Collision Mix-Ups
- If either collider has Is Trigger ticked, you get
OnTriggerEnter2D, notOnCollisionEnter2D, and the objects pass through each other. - If neither is a trigger, you get collision methods and they bounce or block.
“My player walks through the enemy and nothing happens” often means the enemy collider is a trigger but your script only has OnCollisionEnter2D. Pick one behaviour and use the matching method. You can also have both: a solid collider for blocking plus a slightly larger trigger collider for detection.
Layers and the 2D Collision Matrix
Open Edit > Project Settings > Physics 2D and find the Layer Collision Matrix. It’s separate from the 3D one under Physics. If the tick between two layers is off, those layers ignore each other.
Also check:
- Layer Overrides on each Collider2D and Rigidbody2D (Include Layers / Exclude Layers, plus Contact Capture layers). These can exclude layers per object.
- Physics2D.IgnoreCollision or
IgnoreLayerCollisioncalls in your code that you forgot about. - Platform Effector 2D on one-way platforms, which deliberately ignores contacts from some directions.
The collision layers guide explains a good layer setup for small games.
Fast Objects Passing Through
A bullet moving 50 units per second travels a full unit each physics step. If walls are thinner than that, the bullet is in front of the wall on one step and behind it on the next. No overlap, no event.
- Set the bullet’s Rigidbody2D Collision Detection to Continuous.
- Move it with velocity, not by setting
transform.position. Teleporting skips collision checks entirely. - For very fast hitscan-style shots, use
Physics2D.Raycastfrom the old position to the new one each step.
Tilemap Colliders
Tilemaps need a TilemapCollider2D. Tiles also need their Collider Type set to Sprite or Grid in the tile asset, or they produce no shape. For smoother walls and better performance, add a CompositeCollider2D: in Unity 6, set the TilemapCollider2D’s Composite Operation to Merge. Adding a Composite adds a Rigidbody2D; set it to Static so the level doesn’t fall. The Tilemap and Rule Tile tutorial walks through it.
📚 Get comfortable with game physics
Once you understand bodies, contacts and timesteps, these bugs take seconds to fix. See our recommended game dev books for clear explanations.
Troubleshooting
OnTriggerEnter2D not called
Check one object has a Rigidbody2D, one collider is a trigger, both are 2D, and the parameter is Collider2D.
OnCollisionEnter2D not called but objects block each other
The script isn’t on either colliding object or its Rigidbody2D’s GameObject, or the parameter type is wrong.
Kinematic player passes through walls
Kinematic bodies aren’t stopped by colliders. Use a Dynamic body, or cast ahead and stop movement yourself.
Collision works once then stops
Something disables the collider, changes the layer, or turns off Simulated after the first hit. Watch the Inspector in Play Mode.
Player gets stuck on tile edges
Separate tile colliders have seams. Merge them with a CompositeCollider2D and use a capsule collider on the player.
FAQ
Do both objects need a Rigidbody2D?
No, only one. Static level geometry should usually have none.
Do events fire on child colliders?
Collision and trigger messages go to the GameObject with the collider and also to the GameObject with the Rigidbody2D it’s attached to.
Why does OnTriggerStay2D stop firing?
A Dynamic Rigidbody2D can go to sleep when it stops moving. Set Sleeping Mode to Never Sleep if you need constant stay events.
Can a 2D game use 3D colliders?
Yes, but then everything that interacts must be 3D. Never mix the two.
How do I get the contact point?
In OnCollisionEnter2D, read collision.GetContact(0).point and .normal.
Reader questions
Asked by readers of this article and answered by AI. Behavior can differ between Unity versions, so test in yours.




Leave a Reply