Voltar para o Blog
Quest Log

LayerMask e Layer Collision Matrix na Unity

Grade de caixas marcadas e desmarcadas ao lado de inimigos que se atravessam e um projétil passando pelo atirador

Unity LayerMask pelo uso: inimigo que não colide com inimigo, tiro que ignora quem atirou e raycast só no chão, com Layer Collision Matrix e bits.

Ferramenta:UnityC#

LayerMask e Layer Collision Matrix na Unity

Unity LayerMask é o filtro que diz quais layers uma operação de física deve considerar: um raycast que só enxerga o chão, uma explosão que só atinge inimigos, uma câmera que não desenha a interface. A Layer Collision Matrix é a tabela do projeto que diz quais pares de layers colidem entre si. Com as duas você resolve sem código problemas que, com tags, viram uma pilha de if: inimigos que não se empurram, tiro que não acerta quem atirou e ground check que não confunde o próprio jogador com o chão.

Este post explica layers pelo uso em jogo, mostra a matriz de colisão do Unity 6.3 LTS em 3D e 2D, o LayerMask no Inspector e por código, e as operações de bit que você precisa sem decorar binário.

Unity LayerMask: layers vs tags

Os dois aparecem no topo do Inspector e parecem a mesma coisa. Não são.

TagLayer
Quem usaO seu códigoA engine e o seu código
QuantasIlimitadas32 (índices 0 a 31)
Quantas por objetoUmaUma
Filtra físicaNãoSim (matriz e máscaras)
Filtra raycastNãoSim
Filtra câmera e luzNãoSim (Culling Mask)

A regra prática: tag responde "o que é isso?", layer responde "com o que isso interage?". Se o filtro deveria valer antes do seu código rodar (o objeto nem deveria colidir, o raio nem deveria parar), é layer.

O limite de 32 vem do formato: a máscara é um número inteiro de 32 bits, e cada bit é uma layer ligada ou desligada. A referência do LayerMask no Unity 6.3 descreve exatamente isso: bitmasks representando as 32 layers.

Criar layers

  1. Selecione qualquer GameObject e clique no menu Layer no topo do Inspector.
  2. Escolha Add Layer.... Abre a página Tags and Layers (também em Edit > Project Settings > Tags and Layers).
  3. Preencha um dos campos User Layer vazios com um nome.

Algumas posições já vêm ocupadas pela Unity: Default (0), TransparentFX (1), Ignore Raycast (2), Water (4) e UI (5). As outras são suas.

Um conjunto de partida que funciona para a maioria dos jogos de ação:

LayerQuem fica nela
CenarioChão, paredes, plataformas
JogadorCorpo do jogador
InimigoCorpo dos inimigos
TiroJogadorProjéteis do jogador
TiroInimigoProjéteis dos inimigos
ColetavelMoedas, itens
SensorTriggers de área (checkpoint, visão)

Pense em layers como papéis na física, não como tipos de objeto. "Goblin" e "Esqueleto" não precisam de layers separadas se interagem com o mundo do mesmo jeito: os dois são "Inimigo".

Ao mudar a layer de um objeto com filhos, a Unity pergunta se quer aplicar aos filhos também. Para personagem com colliders em filhos, normalmente sim.

Layer Collision Matrix: quem colide com quem

A matriz é uma tabela triangular com todas as layers nas linhas e nas colunas. Cada caixinha marcada diz "esses dois pares colidem e trocam eventos". Desmarcada, os colliders das duas layers se atravessam e nenhum OnCollisionEnter ou OnTriggerEnter acontece entre eles.

Onde fica:

  • 3D: Edit > Project Settings > Physics, seção Layer Collision Matrix.
  • 2D: Edit > Project Settings > Physics 2D, aba Layer Collision Matrix.

São duas matrizes independentes. Configurar a 3D e testar um jogo 2D é um erro clássico.

Os três casos do começo, resolvidos na matriz:

Inimigos não se empurram. Desmarque Inimigo x Inimigo. Eles se sobrepõem em vez de formar fila no corredor, e ninguém trava a horda.

Tiro não acerta quem atirou. Desmarque TiroJogador x Jogador e TiroInimigo x Inimigo. Aproveite e desmarque TiroJogador x TiroInimigo se tiros não devem se anular, e TiroJogador x TiroJogador para os projéteis não baterem uns nos outros quando a arma dispara rápido.

Coletável não vira obstáculo. Deixe Coletavel marcado só com Jogador. Inimigos e tiros passam reto pela moeda.

Isso tudo é configuração, sem uma linha de código. A física nem calcula os pares desmarcados, o que também economiza processamento numa cena cheia.

Para um caso pontual (a granada não deve bater no próprio lançador, mas deve bater em outros jogadores da mesma layer), use Physics.IgnoreCollision entre os dois colliders específicos, em vez de mexer na matriz inteira:

Physics.IgnoreCollision(colliderGranada, colliderLancador, true);

Em 2D, o equivalente é Physics2D.IgnoreCollision. Por código, a matriz inteira pode ser alterada com Physics.IgnoreLayerCollision(layerA, layerB, true), que recebe índices de layer.

Layers e máscaras parecem detalhe até o projeto ter vinte tipos de objeto. A partir daí, cada bug de "atravessou", "não acertou" ou "acertou o que não devia" passa por elas, e quem aprende sozinho costuma descobrir a matriz só depois de encher o código de if (tag == ...). O curso de Unity organiza layers, colisão e dano desde o início de um jogo completo, então a estrutura nasce pronta para crescer.

Curso de Unity
Quer fazer seu primeiro jogo na Unity?

No curso de Unity 6 da CursoGame.Dev você vai do zero ao primeiro jogo, com um desafio prático em cada level e suporte individual no WhatsApp quando travar.

Conhecer o curso de Unity
Suporte no WhatsAppAcesso vitalícioGarantia de 7 dias

LayerMask no Inspector

Declare um campo LayerMask serializado e o Inspector mostra um menu com caixas para marcar as layers:

[SerializeField] private LayerMask layersChao;

É a forma mais segura de configurar máscaras: você escolhe pelo nome, não há número mágico no código e o designer consegue ajustar sem abrir o script. Se você renomear uma layer em Tags and Layers, a máscara continua apontando para o mesmo bit.

Além do raycast, o mesmo campo serve para Physics.OverlapSphere (explosão que só pega inimigos), para a Culling Mask da câmera (minimapa que só desenha ícones) e para as propriedades Include Layers e Exclude Layers de Rigidbody e Collider, que sobrescrevem a matriz só para aquele objeto.

LayerMask no raycast

Arquivo SensorChao.cs, ground check que só enxerga o cenário, com máscara vinda do Inspector e um fallback por nome:

using UnityEngine;

public class SensorChao : MonoBehaviour
{
    [SerializeField] private LayerMask layersChao;
    [SerializeField] private float distancia = 1.1f;

    public bool NoChao { get; private set; }

    private void Awake()
    {
        // Se ninguém configurou no Inspector, monta a máscara pelo nome.
        if (layersChao.value == 0)
        {
            layersChao = LayerMask.GetMask("Cenario");
        }
    }

    private void FixedUpdate()
    {
        NoChao = Physics.Raycast(transform.position, Vector3.down, distancia, layersChao);
    }
}

LayerMask.GetMask recebe nomes e devolve a máscara pronta, com os bits ligados. Aceita vários nomes: LayerMask.GetMask("Cenario", "Plataforma").

Sem máscara, o raycast usa as layers padrão, que incluem a do jogador. Um raio saindo de dentro da cápsula do jogador é ignorado pela física 3D, mas em 2D ele acerta o próprio collider com a configuração padrão do projeto. A máscara elimina essa dúvida nos dois casos. Os detalhes do raycast estão no post de Raycast na Unity.

Operações de bit sem decorar

Você não precisa pensar em binário. Basta lembrar que cada layer é um interruptor, e que 1 << indice é "o interruptor da layer indice". Com isso, cinco operações cobrem tudo:

QueroCódigo
Máscara de uma layer pelo índiceint m = 1 << indice;
Ligar uma layer na máscaramascara |= 1 << indice;
Desligar uma layer da máscaramascara &= ~(1 << indice);
Saber se a máscara contém a layer(mascara & (1 << indice)) != 0
Tudo menos uma layerint m = ~(1 << indice);

Arquivo UtilLayers.cs, um utilitário para não reescrever isso em todo script:

using UnityEngine;

public static class UtilLayers
{
    public static bool Contem(LayerMask mascara, int indiceLayer)
    {
        return (mascara.value & (1 << indiceLayer)) != 0;
    }

    public static LayerMask Adicionar(LayerMask mascara, int indiceLayer)
    {
        return mascara.value | (1 << indiceLayer);
    }

    public static LayerMask Remover(LayerMask mascara, int indiceLayer)
    {
        return mascara.value & ~(1 << indiceLayer);
    }
}

Uso típico, numa bala que só reage às layers configuradas:

[SerializeField] private LayerMask layersQueSofremDano;

private void OnCollisionEnter(Collision collision)
{
    if (!UtilLayers.Contem(layersQueSofremDano, collision.gameObject.layer))
    {
        return;
    }
    // aplica dano
}

O retorno LayerMask dos métodos funciona porque existe conversão implícita de int para LayerMask, documentada na própria classe.

Erros comuns: índice da layer vs máscara

Passar o índice onde se espera a máscara. É o erro número um. gameObject.layer e LayerMask.NameToLayer("Chao") devolvem o índice (por exemplo, 8). O raycast espera a máscara. Passar 8 como máscara significa "só a layer 3", porque 8 é o bit 3. Converta com 1 << indice ou use GetMask.

NameToLayer com nome errado. Devolve -1, e 1 << -1 produz uma máscara sem sentido. Confira o retorno ou prefira o campo no Inspector.

Máscara vazia. Um LayerMask serializado começa como Nothing. Esquecer de marcar no Inspector faz o raycast nunca acertar. O fallback do SensorChao cobre esse caso.

Configurar a matriz 3D num jogo 2D. São matrizes separadas. Confira em Physics 2D.

Layer no pai, collider no filho. A física usa a layer do GameObject que tem o collider. Se o filho ficou na Default, a matriz trata ele como Default.

Usar layer como tipo de objeto. Criar uma layer para cada inimigo esgota as 32 rapidamente e não traz nada. Layer é papel na física; tipo de objeto é componente ou tag.

Ignore Raycast esquecida. A layer 2 é ignorada por raycasts que usam as layers padrão. Um objeto que alguém colocou nela "some" para todos os raios sem máscara explícita.

Próximo passo

Crie as layers da tabela de partida num projeto de teste, configure a matriz para os três casos (inimigos que se atravessam, tiro que não acerta o atirador, moeda só para o jogador) e solte dez inimigos num corredor estreito. Depois mude Inimigo x Inimigo de volta para marcado e veja a fila se formar.

Se você usa Godot também, o post sobre collision layers e masks no Godot mostra o mesmo conceito com uma diferença interessante: lá cada objeto tem uma layer (onde está) e uma mask (o que enxerga) separadas. E para organizar o código que reage a essas colisões sem espalhar if por todo lado, o post de padrões de projeto para jogos mostra componentes e interfaces aplicados a jogo.

Perguntas frequentes

Quantas layers a Unity permite?

São 32 layers por projeto, numeradas de 0 a 31, porque a máscara é um inteiro de 32 bits. Algumas das primeiras já vêm ocupadas pela Unity (Default, TransparentFX, Ignore Raycast, Water e UI) e as demais ficam livres para você nomear em Tags and Layers.

Qual a diferença entre layer e tag na Unity?

Tag é um rótulo para o seu código perguntar o que um objeto é. Layer é uma categoria que a própria engine usa para filtrar física, raycast, câmera e luz. Se o filtro deve valer para a física ou para a renderização, use layer; se é só identificação no script, tag resolve.

Por que LayerMask.NameToLayer não funciona no raycast?

NameToLayer devolve o índice da layer (por exemplo, 8), e o raycast espera uma máscara de bits. Passar 8 como máscara significa a layer 3, porque 8 em binário é o bit 3 ligado. Converta com 1 << LayerMask.NameToLayer("Chao") ou use LayerMask.GetMask("Chao"), que já devolve a máscara.

Onde fica a Layer Collision Matrix no Unity 6?

Para a física 3D, em Edit > Project Settings > Physics. Para a física 2D, em Edit > Project Settings > Physics 2D, na aba Layer Collision Matrix. São duas matrizes independentes: mexer em uma não altera a outra.