Collision detection is the system that tells you when two GameObjects touch each other. When a collision happens, Unity automatically calls special methods in your scripts, allowing you to respond like reducing health, playing a sound, or destroying an object.
Collision Event Methods
Unity provides three collision events that you can use in your scripts:
- OnCollisionEnter: Best for most cases (damage, item pickup, death).
- OnCollisionStay: Use for continuous effects (melting, burning).
- OnCollisionExit: Use for leaving detection (stopping sound effects).
Example
public class Player : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
// Runs ONCE when two objects first touch
Debug.Log("Collision started with: " + collision.gameObject.name);
}
void OnCollisionStay(Collision collision)
{
// Runs EVERY FRAME while objects remain touching
Debug.Log("Still touching...");
}
void OnCollisionExit(Collision collision)
{
// Runs ONCE when objects separate
Debug.Log("Collision ended");
}
}
Collision Parameter
It gives you useful information about the impact:
- collision.gameObject: The object we collided with
- collision.relativeVelocity: Speed of impact (high = hard hit)
- collision.contacts[0].point: World position of collision
Requirements for Collision Events to Fire
For OnCollisionEnter/Stay/Exit to work:
- Both objects must have Collider components.
- At least one object must have a non-kinematic Rigidbody.
- Neither Collider should be marked as "Is Trigger".
Not working? Check these:
- Is Rigidbody missing? Add one.
- Is "Is Trigger" checked? Uncheck it (use triggers for overlap detection).
- Is Rigidbody kinematic? Set to non-kinematic.
Practical Examples
Example 1: Player takes damage when hitting enemy
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
health -= 10;
Debug.Log("Hit! Health: " + health);
}
}
Example 2: Bullet destroys on impact
void OnCollisionEnter(Collision collision)
{
// Ignore collision with shooter
if (collision.gameObject == shooter) return;
Destroy(gameObject); // Destroy bullet
}
Example 3: Play sound based on impact speed
void OnCollisionEnter(Collision collision)
{
float volume = collision.relativeVelocity.magnitude / 10;
AudioSource.PlayClipAtPoint(impactSound, transform.position, volume);
}
Collision vs Trigger
| Feature | Collision | Trigger |
|---|---|---|
| Method to Use | OnCollisionEnter() | OnTriggerEnter() |
| Physical Interaction | Objects physically collide (block each other) | Objects do not block (only overlap detection) |
| Is Trigger Option | Not checked | Must be checked |
| Use Case | Solid objects (walls, floors, enemies) | Detection only (coins, checkpoints, pickups) |
Performance Considerations
- Keep collision code lightweight as it is called frequently.
- Avoid Find() or heavy operations inside collision methods.
- Use tags or layers instead of GetComponent when possible (faster).
- Cache components in Start() instead of getting them in collision.
Common Mistakes
- Using OnTriggerEnter when objects need to physically block - Use OnCollisionEnter instead
- Forgetting Rigidbody: Collision events won't fire
- Moving objects via Transform instead of physics: Causes inconsistent collisions
- Checking collision.gameObject.tag == "Enemy" (expensive) – Use CompareTag() instead