Layers and LayerMask
Part of the Physics and Gameplay section of Coddy's Unity journey. Lesson 36 of 63.
Every GameObject sits on one layer, picked in the Layer menu at the top of the Inspector. Unity has 32: a few are built in (0 Default, 2 Ignore Raycast, 4 Water, 5 UI), and you name your own in Tags and Layers, starting at User Layer 3. A LayerMask is a set of layers, one bit per layer. Pass one to a raycast after maxDistance, and the ray ignores every collider on a layer outside the set.
This player should jump from the ground, not from the heads of enemies. The floors go on a Ground layer, and the script gets a LayerMask field, which the Inspector shows as a menu where you tick Ground:
[SerializeField] private LayerMask groundMask;
bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, 1.1f, groundMask);
}A Ground-only mask also keeps the check from finding the player. A ray skips the collider it starts inside, but not the player's other colliders, such as a child's, and the overlap tests of a later lesson do find the player's own collider, so a check at the feet with no mask would always say grounded. Put the player and its children on a Player layer and keep Player out of the masks its checks use. In code, LayerMask.GetMask("Ground", "Platform") builds a mask from layer names, and ~ in front of a mask flips it into every layer it did not hold.
Challenge
MediumThe scout should report what is ahead, but LookAhead() always returns Lantern. Its ray skips the Scout's body, which it starts inside, then runs into the lantern the Scout holds out in front. The Scout and its Lantern are on the Player layer. Fix LookAhead() in Spotter:
- Build a mask of every layer except Player in code, with
LayerMask.GetMask. - Pass it to the raycast, which keeps its
range, so the ray passes the lantern and reports the first thing beyond it.
Press Play and turn the scout with the arrows: the Console logs what it sees. Then Check.
Try it yourself
using UnityEngine;
public class Spotter : MonoBehaviour
{
public float range = 10f;
private string last = "";
void Update()
{
string seen = LookAhead();
if (seen != last)
{
Debug.Log("Ahead: " + seen);
last = seen;
}
}
// The name of the first thing ahead within range, or "nothing".
public string LookAhead()
{
if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hit, range))
{
return hit.collider.name;
}
return "nothing";
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Physics and Gameplay
1Rigidbody
Gravity and MassPush with AddForceJump with an ImpulseFixedUpdate for PhysicsVelocityKinematic BodiesRecap: Launch Pad2Collisions
OnCollisionEnterWhat Did I Hit?Break on ImpactStanding on the GroundBounce and FrictionCollider ShapesRecap: Breakable Wall6Raycasts
Physics.RaycastRaycastHitGround Check with a RayLayers and LayerMaskLine of SightOverlapSphere and SphereCastRecap: Laser Tripwire