Menu
CoddyTech

Слои и LayerMask

Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 38 из 71.

Каждый GameObject находится на одном слое, выбранном в меню Layer в верхней части Inspector. В Unity есть 32 слоя: некоторые встроены (0 Default, 2 Ignore Raycast, 4 Water, 5 UI), а свои можно назвать в разделе Tags and Layers, начиная с User Layer 3. LayerMask — это набор слоёв, по одному биту на слой. Передайте его в raycast после maxDistance, и луч будет игнорировать все коллайдеры на слоях, не входящих в набор.

Этот игрок должен прыгать с земли, а не с голов врагов. Разместите полы на слое Ground, а скрипту добавьте поле LayerMask, которое Inspector отображает как меню, где можно отметить Ground:

[SerializeField] private LayerMask groundMask;

bool IsGrounded()
{
    return Physics.Raycast(transform.position, Vector3.down, 1.1f, groundMask);
}

Маска, включающая только Ground, также не позволит проверке обнаружить игрока. Луч пропускает коллайдер, внутри которого начинается, но не другие коллайдеры игрока, например коллайдер дочернего объекта; кроме того, проверки перекрытия из следующего урока обнаруживают собственный коллайдер игрока. Поэтому проверка у ног без маски всегда будет сообщать, что игрок стоит на земле. Поместите игрока и его дочерние объекты на слой Player и исключите Player из масок, используемых проверками. В коде LayerMask.GetMask("Ground", "Platform") создаёт маску по именам слоёв, а ~ перед маской инвертирует её, включая все слои, которых в ней не было.

challenge icon

Задание

Средне

Сделай так, чтобы луч разведчика проходил сквозь его собственный фонарь.

  1. В LookAhead() создай int mask = ~LayerMask.GetMask("Player");: все слои, кроме Player, на котором находятся разведчик и его фонарь.
  2. Передай mask в вызов raycast после range.

Нажми «Играть» и поворачивай разведчика стрелками: в Console появятся названия «Камень» и «Дерево». Затем нажми «Проверить».

Попробуйте сами

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;
        }
    }

    // Имя первого объекта впереди в пределах range или "nothing".
    public string LookAhead()
    {
        if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hit, range))
        {
            return hit.collider.name;
        }
        return "nothing";
    }
}

Все уроки раздела Физика и игровой процесс

Потренируйтесь самостоятельно: Песочница Unity