UNITY COLLISION LAYERS & LAYER COLLISION MATRIX

Slash physics CPU overhead by up to 60% by pruning unneeded collider interactions, mastering bitmask LayerMasks, and structuring multi-faction combat layers.

1. The $O(N^2)$ Physics Broadphase Problem

By default, every layer in a new Unity project is set to collide with every other layer. If you have 500 bullets, 50 enemies, debris fragments, and terrain, PhysX evaluates pairwise bounding box overlaps across all combinations during every FixedUpdate.

Pruning the Layer Collision Matrix (in Project Settings > Physics) ensures PhysX instantly skips pairs that should never interact (e.g. PlayerProjectiles colliding with PlayerProjectiles or Debris with Debris).

2. Battle-Tested Combat Layer Setup

Recommended Layer Setup
Layer 8: Player
Layer 9: Enemy
Layer 10: PlayerProjectile
Layer 11: EnemyProjectile
Layer 12: Obstacle / Terrain
Layer 13: Debris / VisualFX
Collision Matrix Rules
❌ PlayerProjectile vs Player (No friendly fire)
❌ PlayerProjectile vs PlayerProjectile
❌ EnemyProjectile vs Enemy
❌ Debris vs Everything except Terrain

3. Efficient LayerMask Filtering in C#

In C#, a LayerMask is a 32-bit integer where each bit represents a layer (from 0 to 31). Never use string comparisons (hit.transform.tag == "Enemy") inside high-frequency Raycasts:

using UnityEngine;

public class HighSpeedLaser : MonoBehaviour
{
    [Header("Raycast Target Filter")]
    [Tooltip("Only evaluates hits against these specific layers.")]
    [SerializeField] private LayerMask targetLayers;

    public void FireLaser(Vector3 start, Vector3 direction, float range)
    {
        // ✅ Hardware bitmask check: PhysX completely ignores all non-target colliders
        if (Physics.Raycast(start, direction, out RaycastHit hit, range, targetLayers))
        {
            Debug.Log($"Laser impacted: {hit.collider.name} on layer {LayerMask.LayerToName(hit.collider.gameObject.layer)}");
        }
    }
}

Related Physics Guides & Tools

Frequently Asked Questions

Unity supports a total of 32 layers (indices 0 through 31). Layers 0 through 7 are reserved by Unity for built-in systems (Default, TransparentFX, Ignore Raycast, Water, UI), leaving 24 user-customizable layers (indices 8 through 31).
Use the bitwise OR operator (|) with bitshifts: LayerMask mask = (1 << LayerMask.NameToLayer("Enemy")) | (1 << LayerMask.NameToLayer("Obstacle"));. Alternatively, expose [SerializeField] private LayerMask mask; to let designers select layers from a dropdown multi-select.