Physics Layers and the Collision Matrix
Unity's thirty two physics layers and the grid of checkboxes that pairs them are a small, unglamorous system, yet they decide which objects can ever meet, and they save both processor time and a great deal of tangled code.

Every physics engine is, at bottom, an elaborate machine for answering one question over and over: which things are touching? In a scene with a few objects the question is easy; in a scene with hundreds of arrows, villagers, falling stones and invisible trigger zones, the number of possible pairs grows roughly with the square of the number of objects, and most of those pairs are pairs nobody cares about. An arrow need not collide with the archer who loosed it, and a decorative leaf need not collide with anything at all.
Unity offers a modest, rather old fashioned tool for telling the engine which pairs matter: physics layers, and the grid of checkboxes called the Layer Collision Matrix. Neither is exciting to look at. They sit in project settings among dropdowns that most people visit once and forget. Yet a project that organizes them thoughtfully runs faster, behaves more predictably and contains far less defensive code than one that leaves every object on the Default layer and patches the consequences one by one.
Thirty two drawers
A layer in Unity is a property of a GameObject, an integer index from zero to thirty one, shown in the Inspector as a named dropdown at the top of every object. There are exactly thirty two of them, a number that is not arbitrary: it is the count of bits in a standard integer, and much of the layer system is built on representing sets of layers as the bits of one such number. Each object belongs to one layer at a time, never to two.
Several of the lowest layers are built in and named by Unity, among them Default, TransparentFX, Ignore Raycast, Water and UI. The rest may be named freely in the Tags and Layers section of the project settings, and in practice a project will define layers along the lines of its own physical categories: Player, Enemy, Projectile, Terrain, Interactable, Ragdoll. Names exist only for the convenience of people; underneath, the engine knows only the index, which is why renaming a layer is harmless while reordering layers can break saved masks throughout a project.
Thirty two sounds generous until a project starts using layers for every passing distinction. Layers also serve the rendering side, where a Camera's culling mask uses them to decide what to draw, and lights use them to decide what to illuminate. A team that spends layers carelessly on single purpose categories may find itself rationing them late in production. The healthiest habit is to define layers by how objects should interact physically and visually, and to use other mechanisms for distinctions that matter only to game logic.
Child objects do not inherit a layer automatically when the parent changes at runtime; setting gameObject.layer affects only that one object. A ragdoll, a weapon with several colliders, or a building assembled from many pieces will need its layer set recursively across the hierarchy, and forgetting this produces a curious half state in which a character's torso ignores arrows while its arms still catch them. The Editor offers to change children when a layer is chosen in the Inspector, but code must do the walk itself.
The matrix itself
The Layer Collision Matrix lives under Edit, then Project Settings, then Physics, and appears as a triangle of checkboxes with layer names running down one side and along the top. Each checkbox represents an unordered pair of layers, which is why the grid is a triangle rather than a square: Enemy against Projectile is the same pair as Projectile against Enemy. A ticked box means colliders on those two layers can collide and generate contacts; an unticked box means the engine will never even consider them as a pair.
The diagonal of the triangle concerns layers against themselves, and it is often the most interesting column. Should projectiles collide with other projectiles? In most games the answer is no, because two arrows meeting in mid flight produce nothing but chaos and wasted computation. Should enemies collide with other enemies? Perhaps yes, so that a crowd pushes and spreads rather than stacking into a single impossible point. Each of these decisions, made once in the matrix, replaces code that would otherwise have to filter collisions in every OnCollisionEnter in the project.
The matrix affects both solid collisions and trigger events, so an unticked pair produces neither OnCollisionEnter nor OnTriggerEnter. It is a project wide setting, which is its strength and its limit. For exceptions that must change at runtime there is Physics.IgnoreLayerCollision, which toggles a pair of layers from code, and Physics.IgnoreCollision, which does the same for two specific colliders. The second is the natural tool for an arrow that must not strike the bow it was fired from during the first instant of its flight.
Unity's 2D physics is a separate engine with its own settings, and it has its own matrix under Physics 2D. A project mixing 2D and 3D physics must configure both, and a developer who has carefully set up one grid may be baffled to find sprites colliding freely because the other grid still has every box ticked, as both do by default.
Masks and bits
When code needs to refer to a set of layers, for a raycast or an overlap query, it uses a LayerMask, which is a bitmask: an integer where bit number n is set if layer n belongs to the set. A mask containing only layer 8 is therefore the integer with only its ninth binary digit on, which is two raised to the eighth power, or 256. A mask containing layers 8 and 9 is 256 plus 512, which is 768.
Programmers build such masks with the left shift operator, shifting the number one left by the layer index; shifting one left by eight places yields 256, exactly the single bit for layer 8. Combining layers uses the bitwise or operator, testing membership uses bitwise and, and inverting a mask, to mean every layer except these, uses the bitwise complement. Most code avoids this arithmetic by calling LayerMask.GetMask with layer names, or LayerMask.NameToLayer to turn a single name into an index, which reads more plainly.
The single most common bug in this area is confusing a layer index with a layer mask. A layer index is a small number from zero to thirty one; a mask is a set encoded in bits. Passing the index 8 where a mask is expected does not mean layer 8; it means the set whose only member is layer 3, since 8 in binary has only its fourth digit on. The query then searches the wrong layer and fails without complaint, and the programmer stares at a perfectly good collider that refuses to be hit.
What it saves
The performance argument for the matrix rests on where in the pipeline the filtering happens. Collision detection proceeds in stages. A broadphase first finds pairs of objects whose bounding volumes overlap, using cheap approximations; a narrow phase then examines the actual shapes of those candidate pairs and computes contact points. Pairs of layers disabled in the matrix are excluded from consideration early, so they never reach the more expensive stages of contact generation and solving.
The saving is greatest where many objects crowd into the same space without needing to interact. A swarm of particles with colliders, a field of debris that should only touch the ground, a horde of creatures whose bodies should strike walls and the player but pass freely through one another: each of these, left on the Default layer, would generate a dense web of contacts that the solver must resolve every physics step. Separated by layer and pruned in the matrix, the same scene asks the engine to resolve only the meetings that have consequences.
The logical saving is harder to measure and perhaps more valuable. Without layers, every collision callback must begin by asking what it has touched and returning early if the answer is uninteresting. Such guards multiply across scripts, each written slightly differently, each a place where a forgotten case lets an arrow damage its own archer. With the matrix configured, many of those callbacks are never invoked at all, and the code that remains concerns itself only with collisions that matter.
Tags are something else
Unity also offers tags, and newcomers often confuse them with layers, since both appear at the top of the Inspector and both seem to label objects. A tag is a single string attached to a GameObject, with Untagged as the default and a handful of built in names such as Player and MainCamera. Each object carries exactly one tag. Tags have no effect on physics whatever; the engine does not consult them when deciding what collides, and no query can be filtered by them directly.
Tags exist for identification in code. A script that has received a collision can call CompareTag on the other object to ask whether it is the player, an enemy or a pickup. CompareTag is preferred over comparing the tag property with a string, because reading the tag property allocates a new string each time, while CompareTag performs the comparison without allocation. GameObject.FindWithTag can locate an object by tag, though searching the scene at runtime is a habit best kept out of anything called every frame.
The sensible division of labor, then, is this: layers decide what can physically interact and what queries may see; tags, or better still components, identify what a thing is once an interaction has occurred. Many experienced developers lean on components for identity, checking whether a collider's object has an Enemy or Health component through TryGetComponent, because a component carries data and behavior while a tag carries only a word. Layers remain irreplaceable, however, because no component can stop a collision before the physics engine computes it.
A plan for the grid
The best time to design the layer scheme is early, before hundreds of prefabs have been built on Default. A practical approach is to list the physical roles in the game and draw the matrix on paper first, asking for each pair whether anything should happen when they meet. A settlement game like Crown & Ashes, for instance, might want the dead that come at night to strike palisades and villagers but pass through the decorative grass, and that single sentence already implies several layers and several unticked boxes.
It helps to keep a dedicated layer for objects that must have colliders but should only ever be queried, never collided with, such as selectable building footprints or interaction zones, and another for purely visual debris that collides with terrain alone. Ragdolls frequently earn their own layer, so that their limbs do not fight the living character's capsule during the transition from animation to physics. Each such decision is small, and their sum is a scene whose physics does exactly what was intended and little else.
Finally, the matrix should be treated as part of the project's design, documented and reviewed like any other system, because a single unticked box can make a feature fail in ways that look like bugs in unrelated code. A programmer who has once spent an afternoon hunting for a broken trigger, only to find that its layer pair was disabled months ago by a colleague tidying the grid, rarely needs to be persuaded of this. The checkboxes are humble, but they are law in the world of the simulation, and they should be written down with the care laws deserve.


