OnTriggerEnter Não Funciona na Unity? Causas e Correções
Se você chegou aqui buscando "Unity OnTriggerEnter not working", a causa quase sempre é uma destas, em ordem de probabilidade: nenhum dos dois objetos tem Rigidbody, o Is Trigger está desmarcado, você misturou física 2D com 3D, o método está escrito com o nome ou o parâmetro errado, a Layer Collision Matrix bloqueia o par, ou um dos objetos está inativo. Cada uma tem um teste de 1 minuto.
Este post é um checklist para seguir de cima para baixo. Cada item diz como confirmar a causa e como corrigir, com código C# para Unity 6.3 LTS. No fim tem um script de diagnóstico que você cola num objeto e ele te diz o que está faltando.
Unity OnTriggerEnter not working: comece aqui
Antes de mexer em qualquer coisa, garanta que você está testando o evento de verdade, e não a lógica dentro dele. Coloque um log como primeira linha do método, antes de qualquer if:
private void OnTriggerEnter(Collider other)
{
Debug.Log($"{name} recebeu trigger de {other.name}", this);
// sua lógica depois
}
Se o log aparece e a moeda não some, o trigger funciona e o problema é a sua lógica (tag errada, if que nunca é verdadeiro). Se o log não aparece, siga o checklist. Confira também se o Console não está com o filtro de mensagens comuns desligado (o ícone de balão no canto superior direito).
Falta Rigidbody em um dos objetos
É a causa número um. A Unity só gera eventos de física quando pelo menos um dos dois objetos tem Rigidbody. Jogador com CharacterController e moeda com collider funcionam (o CharacterController conta como corpo). Mas dois objetos só com collider, movidos por transform.position, nunca trocam mensagem.
Teste de 1 minuto: selecione os dois objetos e procure um componente Rigidbody (ou Rigidbody 2D) no Inspector. Se nenhum dos dois tem, achou.
Correção: adicione Rigidbody ao objeto que se move. Se ele não deve sofrer gravidade nem ser empurrado, marque Is Kinematic. Se a física da Unity ainda é nova para você, o guia de física de jogos explica corpo estático, dinâmico e cinemático com a nomenclatura do Godot, e o conceito é o mesmo. A matriz de interação do manual do Unity 6.3 mostra todas as combinações; a regra prática é: com trigger envolvido, basta um Rigidbody de qualquer tipo em um dos lados.
Uma combinação que engana: dois Kinematic. Dois Kinematic sólidos não geram nada. Um Kinematic sólido contra um Kinematic trigger gera trigger normalmente. Se o seu projétil Kinematic não detecta o inimigo Kinematic, marque o collider de um deles como trigger.
Is Trigger e o tipo de collider
Teste: no Inspector, pelo menos um dos dois colliders precisa estar com Is Trigger marcado. Se nenhum está, os objetos colidem (ou se atravessam, se ambos são Kinematic) e o evento chamado é OnCollisionEnter, não OnTriggerEnter.
Mais dois detalhes do collider:
- MeshCollider num objeto com Rigidbody precisa estar com Convex marcado para funcionar como trigger. Sem Convex, a Unity mostra um aviso no Console.
- Collider desativado (a caixinha ao lado do nome do componente desmarcada) não participa de nada. Às vezes um script desliga o collider no
Starte você esquece.
Confira também o tamanho: um collider com escala zero, ou um BoxCollider com Size minúsculo depois de importar um modelo em escala errada, existe mas nunca encosta em nada. Selecione o objeto na Scene e veja se o contorno verde do collider tem o tamanho que você imagina.
Mistura de 2D e 3D
As físicas 2D e 3D são sistemas separados que não se enxergam. Um BoxCollider2D nunca dispara OnTriggerEnter, e um BoxCollider nunca dispara OnTriggerEnter2D.
Teste: os dois objetos precisam estar no mesmo mundo:
| Física 3D | Física 2D |
|---|---|
Rigidbody | Rigidbody2D |
BoxCollider, SphereCollider, CapsuleCollider, MeshCollider | BoxCollider2D, CircleCollider2D, CapsuleCollider2D, PolygonCollider2D |
OnTriggerEnter(Collider other) | OnTriggerEnter2D(Collider2D other) |
O erro clássico é criar o projeto como 2D, importar um prefab de pacote 3D (ou adicionar "Box Collider" sem o "2D" pela busca do Add Component) e esperar que funcione. Outro: o jogador é 2D e a moeda veio de um tutorial 3D.
Nome ou parâmetro errado do método
A Unity chama esses métodos pelo nome e pelo tipo do parâmetro. Se não bater exatamente, o código compila e o método nunca é chamado, sem erro nenhum.
Declarações erradas que passam pelo compilador sem aviso nenhum:
void OnTriggerEnter(Collision other) // tipo errado: é Collider
void OnTriggerEnter2D(Collider other) // tipo errado: é Collider2D
void OnTriggerEnter2d(Collider2D other) // "2d" minúsculo
void onTriggerEnter(Collider other) // "o" minúsculo
void OnTriggerEnterd(Collider other) // erro de digitação
void OnTriggerEntered(Collider other) // nome inventado
As versões corretas, num arquivo DetectorTrigger.cs:
using UnityEngine;
public class DetectorTrigger : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
Debug.Log($"3D: entrou {other.name}");
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log($"2D: entrou {other.name}");
}
}
Teste: compare letra por letra com o exemplo acima. Se o seu editor de código tem integração com a Unity (Visual Studio ou Rider com o pacote da Unity instalado), digite OnTrig e aceite o autocompletar: ele escreve a versão certa.
Outro ponto: o script precisa estar no mesmo GameObject do collider ou no GameObject do Rigidbody dono daquele collider. Script num objeto pai sem Rigidbody, ou num filho que não tem o collider, não recebe nada.
Se você passou pelos quatro itens acima e o trigger continua mudo, o problema provavelmente está na configuração do projeto (layers) ou no ciclo de vida do objeto, os dois próximos blocos. Esse tipo de bug trava um projeto solo por uma tarde inteira, e é por isso que o curso de Unity trata layers, física e depuração como parte do jogo que você constrói, e não como um apêndice: você monta a cena de um jeito que esses bugs quase não aparecem.
Layer Collision Matrix bloqueando
Cada GameObject tem uma layer (campo Layer no topo do Inspector). A Layer Collision Matrix define quais pares de layers interagem, e um par desmarcado ali não gera colisão nem trigger.
Teste: veja a layer dos dois objetos. Abra Edit > Project Settings > Physics (para 3D) ou Edit > Project Settings > Physics 2D (aba Layer Collision Matrix, para 2D) e confira se o quadradinho na interseção das duas layers está marcado.
Em 3D, o Rigidbody e o collider também têm os campos Include Layers e Exclude Layers (em Layer Overrides), que sobrescrevem a matriz só para aquele objeto. Se alguém colocou a layer do jogador em Exclude Layers, o trigger ignora o jogador mesmo com a matriz certa. O Rigidbody2D tem os mesmos campos.
Não confunda com Queries Hit Triggers (Project Settings > Physics e Physics 2D). Essa opção decide se raycasts e outras consultas acertam colliders trigger. Ela não afeta OnTriggerEnter. Se o seu raycast não acerta a moeda, é ela; se o evento não dispara, não é.
Objeto inativo e Kinematic
Objeto inativo. Um GameObject desativado (SetActive(false) ou a caixa ao lado do nome desmarcada) tem os colliders fora da simulação. Nada entra nele. Se o objeto é ativado já sobrepondo o trigger, o evento dispara no próximo passo de física em que a sobreposição é detectada.
Script desativado. Aqui o comportamento é o contrário do que muita gente espera: a documentação do OnTriggerEnter no Unity 6.3 diz que eventos de trigger são enviados para MonoBehaviours desativados. Se você desmarcou o script achando que ele pararia de detectar, ele continua recebendo o evento. Proteja o método:
private void OnTriggerEnter(Collider other)
{
if (!enabled)
{
return;
}
// lógica
}
OnTriggerExit que nunca vem. Na física 3D, se o objeto que está dentro do trigger é desativado ou destruído, o OnTriggerExit não é garantido. Uma zona que conta "quantos inimigos estão aqui" fica com a contagem errada. Na física 2D existe a opção Callbacks On Disable em Project Settings > Physics 2D, que gera o callback de saída quando um collider com contatos é desativado. Em 3D, avise a zona manualmente antes de destruir o objeto, ou limpe a lista removendo referências nulas.
Kinematic movido pelo transform. Um Kinematic movido com transform.position em vez de rb.MovePosition ainda gera trigger na maioria dos casos, mas pode pular o trigger se andar rápido demais num passo só. Mova Kinematic sempre com MovePosition no FixedUpdate.
Como depurar com Debug.Log e Gizmos
Para não repetir o checklist toda vez, cole este script de diagnóstico no objeto que tem o trigger. Arquivo DiagnosticoTrigger.cs:
using UnityEngine;
public class DiagnosticoTrigger : MonoBehaviour
{
[SerializeField] private Color corGizmo = new Color(0f, 1f, 0f, 0.25f);
private void Start()
{
Collider col3D = GetComponent<Collider>();
Collider2D col2D = GetComponent<Collider2D>();
if (col3D == null && col2D == null)
{
Debug.LogWarning($"{name}: sem Collider nem Collider2D.", this);
return;
}
if (col3D != null)
{
if (!col3D.isTrigger)
{
Debug.LogWarning($"{name}: Collider 3D sem Is Trigger.", this);
}
if (col3D.attachedRigidbody == null)
{
Debug.Log($"{name}: sem Rigidbody. O outro objeto precisa ter um.", this);
}
}
if (col2D != null)
{
if (!col2D.isTrigger)
{
Debug.LogWarning($"{name}: Collider2D sem Is Trigger.", this);
}
if (col2D.attachedRigidbody == null)
{
Debug.Log($"{name}: sem Rigidbody2D. O outro objeto precisa ter um.", this);
}
}
Debug.Log($"{name}: layer = {LayerMask.LayerToName(gameObject.layer)}", this);
}
private void OnTriggerEnter(Collider other)
{
Debug.Log($"[3D] {name} <- {other.name} (layer {LayerMask.LayerToName(other.gameObject.layer)})", this);
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log($"[2D] {name} <- {other.name} (layer {LayerMask.LayerToName(other.gameObject.layer)})", this);
}
private void OnDrawGizmos()
{
Collider col3D = GetComponent<Collider>();
if (col3D != null)
{
Gizmos.color = corGizmo;
Gizmos.DrawCube(col3D.bounds.center, col3D.bounds.size);
}
}
}
O Start aponta o que falta neste lado. Os dois eventos logam qualquer coisa que entre, 2D ou 3D, com a layer do outro objeto. O gizmo pinta o volume do collider na Scene, o que denuncia na hora collider minúsculo ou fora do lugar.
Para ver a física por inteiro, abra Window > Analysis > Physics Debugger. Ele desenha todos os colliders da cena e permite filtrar por layer, útil quando o problema é "esse collider nem está onde eu acho".
Próximo passo
Salve o DiagnosticoTrigger.cs numa pasta de ferramentas do seu projeto e use sempre que um evento sumir. Depois, para entender quando um objeto deveria ser trigger ou colisão desde o começo, leia o comparativo Trigger vs Collision na Unity, que traz a tabela de decisão por tipo de objeto.
Se você também trabalha com Godot, a lista de erros comuns de debug no Godot segue a mesma lógica de diagnóstico em ordem de probabilidade, com as causas equivalentes de lá (collision layer, mask e sinal desconectado).
Perguntas frequentes
Por que OnTriggerEnter2D não funciona?
As causas mais comuns são: nenhum dos dois objetos tem Rigidbody2D, o collider é 3D (BoxCollider) em vez de 2D (BoxCollider2D), o método foi escrito com Collider em vez de Collider2D, ou a Layer Collision Matrix da aba Physics 2D desmarcou o par de layers.
Trigger funciona entre dois objetos Kinematic na Unity?
Funciona se pelo menos um dos dois colliders for trigger. Dois Kinematic sólidos não geram nem colisão nem trigger. Um Kinematic sólido contra um Kinematic trigger dispara OnTriggerEnter normalmente, segundo a matriz de interação do manual do Unity 6.3.
OnTriggerEnter é chamado com o script desativado?
Sim. A documentação do Unity 6.3 diz que eventos de trigger são enviados para MonoBehaviours desativados, para permitir ativar comportamentos em resposta. Se você desmarcou o script para parar a detecção, coloque um if (!enabled) return; no início do método.
Por que OnTriggerExit não é chamado quando destruo o objeto?
Na física 3D, desativar ou destruir um objeto que está dentro do trigger não garante o OnTriggerExit. Na física 2D, a opção Callbacks On Disable em Project Settings > Physics 2D gera o callback de saída quando o collider é desativado. Para 3D, avise o trigger manualmente antes de destruir.



