Unity 2D Collision Not Working? OnCollisionEnter2D and OnTriggerEnter2D

Illustration: two flat 2D sprites colliding with a burst of impact lines

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:

  1. Both objects have a 2D collider (BoxCollider2D, CircleCollider2D, CapsuleCollider2D, PolygonCollider2D, TilemapCollider2D and so on).
  2. At least one of them has a Rigidbody2D.
  3. For collision events, the Rigidbody2D setups must be a pair that generates contacts (more on body types below).
  4. Their layers are allowed to collide in the Physics 2D settings.
  5. 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).
  6. 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.
  • OnTriggerEnter2d or OnTriggerEnter (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, not OnCollisionEnter2D, 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 IgnoreLayerCollision calls 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.Raycast from 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.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *