Voltar para o Blog
Quest Log

Trigger vs Collision na Unity: Qual Usar e Quando

Personagem 3D atravessando uma zona translúcida verde enquanto bate numa caixa sólida ao lado

Unity OnTriggerEnter vs OnCollisionEnter: tabela de decisão para moeda, dano, checkpoint e parede, a matriz de quem dispara evento com quem e as versões 2D.

Ferramenta:UnityC#

Trigger vs Collision na Unity: Qual Usar e Quando

A diferença entre Unity OnTriggerEnter vs OnCollisionEnter cabe numa frase: colisão é quando os objetos batem (um impede o outro de passar e a física calcula a resposta), trigger é quando um objeto entra numa área (ninguém impede ninguém, você só é avisado). Parede, chão e caixa empurrável são colisão. Moeda, zona de dano, checkpoint e porta automática são trigger.

O que costuma faltar nas explicações é o critério para casos ambíguos e a regra de quem dispara evento com quem. Este post traz uma tabela de decisão por tipo de objeto de jogo, a matriz oficial de interação entre colliders do Unity 6.3 e as versões 2D de cada evento, com código C# pronto.

Unity OnTriggerEnter vs OnCollisionEnter: a diferença

Os dois eventos nascem da mesma situação (dois colliders se encostando), mas dizem coisas diferentes.

OnCollisionEnter(Collision collision) dispara quando dois colliders sólidos se tocam e a física resolve o contato: o objeto para, quica ou empurra. O parâmetro Collision traz pontos de contato, normal, velocidade relativa e impulso. É informação para reagir a um impacto: tocar som proporcional à força, aplicar dano de queda, gerar faísca no ponto exato.

OnTriggerEnter(Collider other) dispara quando um collider entra no volume de outro que está marcado como trigger. Não há impacto nem ponto de contato, só "entrou". O parâmetro é o Collider do outro objeto, e mais nada.

Cada um tem as variantes Stay (a cada passo de física enquanto continua em contato) e Exit (quando sai).

Arquivo Moeda.cs, o exemplo mais comum de trigger:

using UnityEngine;

public class Moeda : MonoBehaviour
{
    [SerializeField] private int valor = 1;

    private void OnTriggerEnter(Collider other)
    {
        if (!other.CompareTag("Player"))
        {
            return;
        }

        Debug.Log($"Pegou moeda de {valor}");
        Destroy(gameObject);
    }
}

Arquivo CaixaBarulhenta.cs, o exemplo de colisão, que usa a força do impacto:

using UnityEngine;

public class CaixaBarulhenta : MonoBehaviour
{
    [SerializeField] private AudioSource fonteSom;
    [SerializeField] private float impactoMinimo = 2f;

    private void OnCollisionEnter(Collision collision)
    {
        float forca = collision.relativeVelocity.magnitude;
        if (forca < impactoMinimo)
        {
            return;
        }

        fonteSom.volume = Mathf.Clamp01(forca / 10f);
        fonteSom.Play();
    }
}

A moeda não precisa saber onde nem com que força foi tocada. A caixa precisa. Esse é o primeiro critério.

Is Trigger: o que muda no collider

Marcar Is Trigger no Inspector do collider faz duas coisas ao mesmo tempo:

  1. Desliga a resposta física. Nada bate nele, tudo atravessa. Um chão marcado como trigger derruba o jogador no vazio.
  2. Troca os eventos. O objeto deixa de gerar OnCollision* e passa a gerar OnTrigger*.

Não existe meio-termo num único collider. Se o objeto precisa ser sólido e detectar uma área, use dois colliders: um sólido do tamanho do corpo, e outro maior com Is Trigger. Um inimigo com collider sólido para não atravessar paredes e um trigger esférico como "raio de percepção" é o padrão clássico. Se os dois ficam no mesmo GameObject, o mesmo script recebe os dois tipos de evento. Se o trigger fica num filho, o evento chega no script do filho (e também no Rigidbody pai).

Um detalhe do MeshCollider: para ser trigger num objeto que se move com Rigidbody, ele precisa estar com Convex marcado.

Quando usar trigger

Use trigger quando a pergunta é "está dentro?" e você não quer que nada seja barrado:

Objeto de jogoPor que trigger
Moeda, item, power-upColeta sem frear o jogador
Zona de dano (lava, espinho, fogo)Dano contínuo com OnTriggerStay ou por tempo
Checkpoint e fim de faseSó precisa saber que passou
Porta automática, gatilho de cutsceneÁrea de ativação
Área de visão ou audição do inimigoDetecta sem empurrar
Hitbox de ataqueAtiva por poucos frames, detecta quem estava dentro
Água, vento, zona de gravidadeAplica efeito enquanto está dentro

Hitbox merece nota: golpe de espada como trigger ligado por alguns frames da animação é o padrão em jogo de ação. O post sobre hitbox e hurtbox no Godot explica a separação entre "o que bate" e "o que apanha", e a ideia é a mesma na Unity: um trigger por papel.

Quando usar collision

Use colisão quando a pergunta é "bateu?" e a física precisa barrar ou responder:

Objeto de jogoPor que colisão
Chão, parede, tetoBarram o movimento
Caixa, barril, destroçoPrecisam ser empurrados e cair
Projétil físico (flecha, granada)Precisa quicar, cravar ou parar no ponto de impacto
Inimigo que bloqueia passagemO corpo dele ocupa espaço
Dano de queda ou impactoUsa relativeVelocity e impulse
Faísca, decalque de balaUsa o ponto e a normal do contato

Caso ambíguo comum: projétil. Se a bala não precisa quicar nem empurrar, um trigger simples resolve (entrou no inimigo, aplica dano, destrói a bala). Se a granada precisa quicar no chão e explodir depois, é colisão. E se a bala é rápida demais, nem um nem outro: raycast.

Outro caso: inimigo que dá dano por contato. O corpo do inimigo é sólido (colisão para não atravessar o jogador) e o dano pode vir de OnCollisionEnter mesmo. Se você quer que o jogador atravesse o inimigo enquanto toma dano (comum em plataforma 2D com invencibilidade), o corpo vira trigger e a colisão com o cenário fica num segundo collider em outra layer.

Escolher trigger ou colisão para um objeto isolado é simples. Num jogo, as decisões se acumulam: o inimigo tem corpo, área de visão e hitbox; o jogador tem corpo, hurtbox e área de interação; cada um em sua layer. Errar uma peça gera bug que parece aleatório. O curso de Unity monta esse conjunto dentro de um jogo completo, e a organização de colliders e layers é parte do que você constrói lá.

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

Matriz: o que dispara com o quê

Aqui está a regra que explica a maioria dos "meu evento não dispara". A Unity separa colliders em três tipos conforme o Rigidbody:

  • Static: collider sem Rigidbody (cenário).
  • Dynamic: collider com Rigidbody normal (sofre física).
  • Kinematic: collider com Rigidbody marcado como Is Kinematic (movido por código).

Cada um pode ser sólido ou trigger. A página de interação entre tipos de collider do manual do Unity 6.3 traz a matriz completa. Resumida (C = eventos de colisão, T = eventos de trigger, vazio = nada):

StaticDynamicKinematicStatic triggerDynamic triggerKinematic trigger
StaticCTT
DynamicCCCTTT
KinematicCTTT
Static triggerTTTT
Dynamic triggerTTTTTT
Kinematic triggerTTTTTT

Três leituras práticas:

  1. Static com Static nunca dispara nada. Duas paredes, ou uma parede e uma moeda sem Rigidbody, não conversam. O objeto que se move precisa de Rigidbody.
  2. Colisão só sai se um dos lados for Dynamic. Kinematic contra Kinematic ou contra Static não gera OnCollisionEnter. Plataforma Kinematic encostando na parede não avisa.
  3. Trigger é mais generoso. Basta que um dos dois tenha Rigidbody (Dynamic ou Kinematic). Por isso o padrão para coisas que se movem por código e precisam detectar área é: Rigidbody Kinematic + collider trigger.

Versões 2D dos eventos

A física 2D é um sistema separado, com componentes e eventos próprios. Os nomes ganham o sufixo 2D e os parâmetros mudam de tipo:

3D2D
OnTriggerEnter(Collider other)OnTriggerEnter2D(Collider2D other)
OnTriggerStay(Collider other)OnTriggerStay2D(Collider2D other)
OnTriggerExit(Collider other)OnTriggerExit2D(Collider2D other)
OnCollisionEnter(Collision collision)OnCollisionEnter2D(Collision2D collision)
OnCollisionStay(Collision collision)OnCollisionStay2D(Collision2D collision)
OnCollisionExit(Collision collision)OnCollisionExit2D(Collision2D collision)

Arquivo Espinho2D.cs, zona de dano 2D que aplica dano a cada meio segundo enquanto o jogador está dentro:

using UnityEngine;

public class Espinho2D : MonoBehaviour
{
    [SerializeField] private int dano = 1;
    [SerializeField] private float intervalo = 0.5f;

    private float proximoDano;

    private void OnTriggerStay2D(Collider2D other)
    {
        if (!other.CompareTag("Player") || Time.time < proximoDano)
        {
            return;
        }

        proximoDano = Time.time + intervalo;
        Debug.Log($"Espinho causou {dano} de dano");
    }
}

A regra de "um dos dois precisa de Rigidbody2D" vale igual. Uma diferença: em 2D, um Rigidbody2D Kinematic só gera colisão com corpos Dynamic, a menos que você marque Use Full Kinematic Contacts; triggers são exceção e funcionam com qualquer tipo de corpo, segundo o manual de body types do Unity 6.3.

Física 2D e 3D não se enxergam: um BoxCollider2D nunca dispara OnTriggerEnter, e um BoxCollider nunca dispara OnTriggerEnter2D.

Erros comuns

Nenhum dos dois tem Rigidbody. Releia a primeira linha da matriz. Coloque Rigidbody no objeto que se move.

Parâmetro errado no método. OnTriggerEnter(Collision c) ou OnCollisionEnter2D(Collision c) compilam, mas a Unity não chama. Cada evento tem seu tipo de parâmetro exato, como nas tabelas acima. O diagnóstico completo de trigger que não dispara está em OnTriggerEnter não funciona na Unity.

Is Trigger no chão. O jogador cai pelo mapa. Chão é sólido; se precisa de detecção, adicione um segundo collider trigger.

Comparar tag com ==. other.tag == "Player" funciona, mas other.CompareTag("Player") é o jeito recomendado: evita criar uma string nova a cada chamada.

Esperar OnTriggerEnter quando o objeto já nasce dentro. Se o objeto é ativado já sobrepondo o trigger, o evento dispara no primeiro passo de física em que a sobreposição é detectada, não no frame do SetActive. Lógica que depende do momento exato precisa considerar esse atraso.

Usar OnTriggerStay para dano sem controle de tempo. Ele roda a cada passo de física (50 vezes por segundo no padrão). Sem intervalo, o jogador morre num piscar. Use um temporizador como no Espinho2D. E repare num detalhe: se o jogador ficar parado dentro da área e o Rigidbody dele dormir, o Stay para de ser chamado e o dano some. No Rigidbody2D do jogador, troque Sleeping Mode para Never Sleep (no 3D, a alternativa é tratar o dano por Enter/Exit com um timer próprio).

Próximo passo

Monte uma cena com um jogador (Rigidbody + CapsuleCollider), uma moeda (trigger sem Rigidbody), uma caixa (Rigidbody Dynamic) e uma plataforma Kinematic. Coloque um Debug.Log em cada evento e mova o jogador por tudo: confira cada linha da matriz na prática, principalmente a plataforma Kinematic que não avisa colisão com a parede.

Se você também usa Godot, o guia de física de jogos no Godot mostra a mesma divisão com Area e corpos físicos, e ajuda a fixar que o conceito de "área que detecta" e "corpo que bate" é o mesmo nas duas engines.

Perguntas frequentes

O que faz a opção Is Trigger no collider da Unity?

Is Trigger tira o collider da resposta física: nada bate nele, tudo atravessa. Em troca, ele passa a avisar por OnTriggerEnter, OnTriggerStay e OnTriggerExit quando outro collider entra, fica ou sai da área. É o que você quer para moeda, zona de dano e checkpoint.

Por que OnTriggerEnter não é chamado entre dois objetos sem Rigidbody?

A Unity só gera eventos de física quando pelo menos um dos dois objetos tem Rigidbody (ou Rigidbody2D). Dois colliders estáticos nunca trocam mensagens. Coloque um Rigidbody no objeto que se move, marcado como Kinematic se você não quer gravidade.

Posso usar trigger e colisão no mesmo objeto?

Sim, com dois colliders: um sólido para o corpo bater no cenário e outro maior marcado como Is Trigger para detectar coisas por perto. Os dois disparam seus próprios eventos no mesmo script. Um único collider, porém, é ou trigger ou sólido.

Qual a diferença entre OnTriggerEnter2D e OnTriggerEnter?

OnTriggerEnter2D recebe um Collider2D e só funciona com componentes de física 2D (Rigidbody2D e Collider2D). OnTriggerEnter recebe um Collider e só funciona com física 3D. As duas físicas não conversam entre si.