Topic 5 of 15 13 min intermediate

Colliders & Rigidbodies

How Unity decides what touches what

Physics questions are the most common Unity questions, and nearly all of them reduce to one thing: which object has a Rigidbody? Get that right and collisions behave. Get it wrong and events silently never fire.

Two components, two jobs

  • Collider defines the shape used for collision. It has no motion of its own.
  • Rigidbody hands the object to the physics engine, giving it mass, velocity, and gravity.

A collider with no rigidbody is static geometry — walls, floors, level meshes. Unity optimises heavily for these on the assumption they never move.

Moving a collider that has no Rigidbody forces Unity to rebuild its static physics data every time. If a moving platform tanks your frame rate, this is why — give it a Rigidbody set to Kinematic.

The collision matrix

This table answers "why is OnCollisionEnter never called?" more often than anything else. At least one of the two objects must have a non-kinematic Rigidbody.

Does a collision event fire?

Object AObject BResult
Collider onlyCollider onlyNothing. Neither is in the simulation.
Collider + RigidbodyCollider onlyCollision fires. The usual player-vs-wall case.
Collider + RigidbodyCollider + RigidbodyCollision fires, both react.
Kinematic RigidbodyCollider onlyNothing. Kinematic vs static is ignored.
Kinematic RigidbodyCollider + RigidbodyCollision fires. The dynamic one reacts.
Any + Is TriggerAny with RigidbodyTrigger fires instead of collision.
Checklist when nothing fires: does either object have a Rigidbody, are both colliders enabled, is Is Trigger set as you expect, and are the two layers allowed to interact in Project Settings → Physics?

Collisions vs triggers

A collision physically stops things. A trigger detects overlap and lets objects pass straight through. Pickups, checkpoints, and damage zones are triggers; walls and crates are collisions.

C#
private void OnCollisionEnter(Collision collision)
{
    // Physical impact - you get contact points and impulse
    if (collision.gameObject.CompareTag("Ground"))
        isGrounded = true;

    float force = collision.impulse.magnitude;
    if (force > 10f)
        PlayCrashSound(force);
}
Use CompareTag("Player") rather than other.tag == "Player". The property version allocates a string every call, and this runs on every overlap.

Each comes in three flavours: Enter, Stay, and Exit. Stay runs every physics step while contact continues, so keep it cheap.

Moving a Rigidbody

Setting transform.position on a physics object teleports it, skipping collision detection entirely. Fast objects tunnel through walls.

How to move itUse whenNote
rb.AddForce()Realistic accelerationMass matters. Feels weighty.
rb.velocity = vDirect arcade controlIgnores mass. Most 2D platformers.
rb.MovePosition()Kinematic movementRespects collisions. Moving platforms.
transform.positionNon-physics objects onlySkips physics. Tunnelling.
C#
private void FixedUpdate()
{
    // Kinematic platform that still pushes things correctly
    Vector3 next = rb.position + move * speed * Time.fixedDeltaTime;
    rb.MovePosition(next);
}

Fast objects tunnel

Physics is sampled in steps. If a bullet travels further in one step than the wall is thick, it is on one side, then the other, and never in between. Nothing is detected.

  • Set Collision Detection to Continuous on fast rigidbodies.
  • Or skip rigidbodies for bullets and raycast along the path travelled each frame.
  • Making walls thicker genuinely helps, unglamorous as it sounds.
Raycast bullet
C#
private void FixedUpdate()
{
    float step = speed * Time.fixedDeltaTime;

    // Check the path we are about to travel, not just where we are
    if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hit, step))
    {
        hit.collider.GetComponent<Health>()?.TakeDamage(damage);
        Destroy(gameObject);
        return;
    }

    transform.position += transform.forward * step;
}

Collider shapes have costs

ColliderCostNote
SphereCheapestOne distance check.
CapsuleCheapThe standard character shape.
BoxCheapFine for most props.
Mesh (convex)ExpensiveRequired for a moving mesh collider.
Mesh (concave)Most expensiveStatic geometry only.
Approximate complex shapes with several primitive colliders on child objects. Two boxes and a capsule beat a mesh collider almost every time.

Layers keep physics cheap

Every pair of layers can be switched on or off in the collision matrix. Bullets do not need to test against other bullets, and UI never needs physics at all. Turning off pairs you do not need is the cheapest optimisation in the engine.

C#
// Restrict a raycast to a single layer
[SerializeField] private LayerMask groundLayer;

bool grounded = Physics2D.OverlapCircle(feet.position, 0.2f, groundLayer);

What to take away

  • At least one object in a pair needs a non-kinematic Rigidbody, or nothing fires.
  • Colliders without rigidbodies are static — never move them.
  • Triggers detect overlap; collisions apply force.
  • Move physics objects in FixedUpdate with velocity, forces, or MovePosition.
  • Use Continuous detection or raycasts for anything fast.
  • Prefer primitive colliders and switch off unneeded layer pairs.