Summary
Collider2D is the component that defines the physical shape of a 2D GameObject for collision detection. It has two operating modes: solid (objects physically push each other) and trigger (overlap detection only, no physical response). Solid collisions fire OnCollisionEnter2D; trigger overlaps fire OnTriggerEnter2D. The distinction controls whether the physics engine actually pushes objects apart or simply notifies the script that an overlap has begun.
Key ideas
Collider2D types:
| Type | Shape | Common use |
|---|---|---|
BoxCollider2D | Rectangle | Characters, walls, platforms |
CircleCollider2D | Circle | Coins, projectiles, round enemies |
PolygonCollider2D | Arbitrary polygon | Irregular terrain, shaped pickups |
CapsuleCollider2D | Capsule | Humanoid characters |
Is Trigger: When enabled on a Collider2D, that collider no longer blocks movement. It only detects overlap. OnTriggerEnter2D fires when the overlap begins. OnTriggerExit2D fires when it ends. Use for: pickups, hazards, area detectors, exit zones.
Solid collision (Is Trigger off on both colliders): Objects physically block each other. OnCollisionEnter2D fires on contact. Use for: walls, floors, platforms.
OnTriggerEnter2D(Collider2D other): The other parameter is the collider that entered the trigger. Use other.CompareTag("TagName") to identify what type of object it is.
OnCollisionEnter2D(Collision2D collision): The collision parameter provides contact data. collision.gameObject is the other object; collision.contacts[0].normal is the surface direction of the hit.
CompareTag(string tag): The correct way to check an object’s tag. Faster than other.tag == "TagName" because it does not allocate a new string. Unity will log a warning if you compare against a tag name that does not exist in the project.
Destroy(GameObject): Removes a GameObject from the scene. Always call this last in a pickup handler, after all other logic has run, so nothing tries to access the object after it is destroyed.
In practice
Trigger overlap detection (coins, hazards, health packs):
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Coin"))
{
HandleCoin(other.gameObject);
}
else if (other.CompareTag("Hazard"))
{
HandleHazard(other.gameObject);
}
else if (other.CompareTag("HealthPack"))
{
HandleHealthPack(other.gameObject);
}
// Unrecognised tags are silently ignored
}
private void HandleCoin(GameObject coin)
{
score += 10;
Debug.Log("Coin collected! Score: " + score);
Destroy(coin); // call LAST
}Solid collision detection (walls):
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Wall"))
{
Debug.Log("Wall hit. Normal: " + collision.contacts[0].normal);
}
}Invincibility window after taking damage:
[SerializeField] private float invincibilityDuration = 1.5f;
private float invincibilityTimer = 0f;
private bool isInvincible = false;
void Update()
{
if (isInvincible)
{
invincibilityTimer -= Time.deltaTime;
if (invincibilityTimer <= 0f)
{
isInvincible = false;
}
}
}
private void HandleHazard(GameObject hazard)
{
if (isInvincible) return; // blocked during invincibility window
health = Mathf.Max(health - 25, 0);
isInvincible = true;
invincibilityTimer = invincibilityDuration;
}Health pack with Mathf.Min clamp:
private void HandleHealthPack(GameObject pack)
{
health = Mathf.Min(health + 30, maxHealth); // cannot exceed maxHealth
Destroy(pack);
}Setup requirements
For OnTriggerEnter2D to fire, the following must all be true:
- The moving object (e.g. player) must have a Rigidbody2D
- At least one of the two colliders must have Is Trigger enabled
- Both objects must be on layers that interact in the Physics Layer Matrix (Edit > Project Settings > Physics 2D)
- Tags referenced in
CompareTagmust be defined in the project (Edit > Project Settings > Tags and Layers)
Most beginner collision bugs are configuration errors, not code errors. When a trigger is not firing, check these four things before reading the script.
Gotchas
other.tag == "Coin"works but allocates a new string each call. Useother.CompareTag("Coin")instead.- Both
OnTriggerEnter2DandOnCollisionEnter2Dmust be on a script attached to a GameObject that has aCollider2D. They do not fire on a script attached to an empty object with no collider. OnTriggerEnter2Dfires once per overlap start. It will not fire repeatedly while the objects remain overlapping — useOnTriggerStay2Dfor continuous detection.Destroy(gameObject)destroys the object the script is attached to.Destroy(other.gameObject)destroys the other object. Confusing these is a common error.- After calling
Destroy(coin), any further code that referencescoinwill throw aNullReferenceException. Always callDestroylast.
Debugging practice
Use this table before rewriting code. Most trigger bugs are setup bugs.
| Symptom | Likely cause | Fix |
|---|---|---|
OnTriggerEnter2D never runs | No Rigidbody2D on either object | Add Rigidbody2D to the moving object |
| Objects bounce instead of overlap | Is Trigger is off | Enable Is Trigger on the pickup, hazard or detector |
| Code runs for the wrong object | Tag check is missing or wrong | Add the tag in Tags and Layers, then use CompareTag |
| Coin destroys the player | Used Destroy(other.gameObject) in a script on the coin | Destroy the coin with Destroy(gameObject) |
| Trigger works in one scene but not another | Layer collision matrix differs | Check Physics 2D layer settings |
Self-test
- What is the main difference between a trigger and a solid collision?
- What component is required for 2D trigger messages to fire reliably?
- Why should
Destroynormally be called last in a pickup method? - Why is
CompareTag("Coin")preferred overother.tag == "Coin"? - Which object does
Destroy(gameObject)destroy?
Answers
- A trigger detects overlap without pushing objects apart. A solid collision produces physical contact.
- A
Rigidbody2D, normally on the moving object. - Later code may try to access the destroyed object and cause an error.
CompareTagavoids string allocation and warns about missing tags.- The GameObject that this script is attached to.
Related
- unity-rigidbody2d - Rigidbody2D is required on the moving object for triggers to fire
- monobehaviour-lifecycle -
Updatefor the invincibility timer and lifecycle context for collision methods - unity-inspector-references - wiring
GameManagerreferences on pickup scripts - csharp-control-flow -
if/else ifchains in trigger handlers