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:

TypeShapeCommon use
BoxCollider2DRectangleCharacters, walls, platforms
CircleCollider2DCircleCoins, projectiles, round enemies
PolygonCollider2DArbitrary polygonIrregular terrain, shaped pickups
CapsuleCollider2DCapsuleHumanoid 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 CompareTag must 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. Use other.CompareTag("Coin") instead.
  • Both OnTriggerEnter2D and OnCollisionEnter2D must be on a script attached to a GameObject that has a Collider2D. They do not fire on a script attached to an empty object with no collider.
  • OnTriggerEnter2D fires once per overlap start. It will not fire repeatedly while the objects remain overlapping — use OnTriggerStay2D for 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 references coin will throw a NullReferenceException. Always call Destroy last.

Debugging practice

Use this table before rewriting code. Most trigger bugs are setup bugs.

SymptomLikely causeFix
OnTriggerEnter2D never runsNo Rigidbody2D on either objectAdd Rigidbody2D to the moving object
Objects bounce instead of overlapIs Trigger is offEnable Is Trigger on the pickup, hazard or detector
Code runs for the wrong objectTag check is missing or wrongAdd the tag in Tags and Layers, then use CompareTag
Coin destroys the playerUsed Destroy(other.gameObject) in a script on the coinDestroy the coin with Destroy(gameObject)
Trigger works in one scene but not anotherLayer collision matrix differsCheck Physics 2D layer settings

Self-test

  1. What is the main difference between a trigger and a solid collision?
  2. What component is required for 2D trigger messages to fire reliably?
  3. Why should Destroy normally be called last in a pickup method?
  4. Why is CompareTag("Coin") preferred over other.tag == "Coin"?
  5. Which object does Destroy(gameObject) destroy?

Answers

  1. A trigger detects overlap without pushing objects apart. A solid collision produces physical contact.
  2. A Rigidbody2D, normally on the moving object.
  3. Later code may try to access the destroyed object and cause an error.
  4. CompareTag avoids string allocation and warns about missing tags.
  5. The GameObject that this script is attached to.