Voltar para o Blog
Quest Log

Prefab Variant na Unity: Inimigos Diferentes com Base Comum

Quatro inimigos de jogo 2D lado a lado, do pequeno e rápido ao chefe grande, ligados por linhas a um molde comum

Unity prefab variant na prática: monte inimigo base, rápido, tanque e chefe sobrescrevendo só o que muda, e saiba quando variant ganha de ScriptableObject.

Ferramenta:Unity

Prefab Variant na Unity: Inimigos Diferentes com Base Comum

Prefab Variant na Unity é um prefab que herda de outro e guarda só o que é diferente. Você faz um inimigo base com sprite, física, colisão e script, e cria variantes "rápido", "tanque" e "chefe" que mudam velocidade, vida, tamanho e um ou outro componente. Quando você corrige o collider da base, as três recebem a correção. Esse é o uso mais comum de Unity prefab variant e é o que vamos montar aqui, no Unity 6.3 LTS.

No fim você terá uma família de quatro inimigos, vai entender o que a variante herda e o que ela sobrescreve, como isso convive com prefabs aninhados e, a parte que mais gera dúvida, quando a resposta certa não é variant e sim ScriptableObject. Se prefab ainda é novidade, comece pelo guia de prefab na Unity, que cobre Prefab Mode e overrides do zero.

O que é Prefab Variant na Unity

Pense em herança de classe, só que para objetos montados no editor. A base define tudo: hierarquia de filhos, componentes e valores. A variante aponta para a base e registra uma lista de overrides, exatamente como uma instância de prefab na cena faz. A diferença é que essa lista fica salva num asset próprio, reutilizável.

Três regras definem o comportamento:

  1. Campo sem override herda. Se a variante não mexeu no Rigidbody2D, qualquer mudança no Rigidbody2D da base aparece nela.
  2. Campo com override ignora a base. Se a variante "Tanque" definiu maxHealth = 120, mudar a vida da base para 40 não afeta o Tanque.
  3. Variante pode ter base que também é variante. O "Chefe" pode herdar do "Tanque", que herda da base. O manual chama isso de variante de variante e é permitido.

Visualmente, a variante aparece com o ícone de cubo azul com um lado hachurado, tanto na janela Project quanto na Hierarchy.

Criando a variante a partir do prefab base

Primeiro o inimigo base. Crie um GameObject Enemy_Base com:

  • Sprite Renderer com o sprite do inimigo.
  • Rigidbody2D com Gravity Scale 0 (vista de cima) ou 1 (plataforma).
  • CapsuleCollider2D ajustado ao sprite.
  • O script EnemyStats abaixo.

Arquivo EnemyStats.cs:

using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class EnemyStats : MonoBehaviour
{
    [SerializeField, Min(1)] private int maxHealth = 30;
    [SerializeField, Min(0f)] private float moveSpeed = 2f;
    [SerializeField, Min(0)] private int contactDamage = 10;
    [SerializeField] private Transform target;

    private Rigidbody2D rb;
    private int currentHealth;

    public int ContactDamage => contactDamage;

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        currentHealth = maxHealth;
    }

    private void Start()
    {
        if (target == null)
        {
            GameObject player = GameObject.FindWithTag("Player");
            if (player != null)
            {
                target = player.transform;
            }
        }
    }

    private void FixedUpdate()
    {
        if (target == null)
        {
            rb.linearVelocity = Vector2.zero;
            return;
        }

        Vector2 direction = ((Vector2)target.position - rb.position).normalized;
        rb.linearVelocity = direction * moveSpeed;
    }

    public void TakeDamage(int amount)
    {
        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            Destroy(gameObject);
        }
    }
}

O movimento usa Rigidbody2D.linearVelocity, o nome atual da propriedade no Unity 6 (tutoriais antigos usam velocity). O alvo é buscado pela tag Player no Start, porque prefab não guarda referência para objeto da cena.

Arraste Enemy_Base da Hierarchy para Assets/_Project/Prefabs/Enemies. Agora a variante: clique com o botão direito em Enemy_Base.prefab na janela Project e escolha Create > Prefab Variant. A Unity cria o arquivo na mesma pasta. Renomeie para Enemy_Fast. Repita para Enemy_Tank.

Há um segundo caminho: arrastar para a janela Project uma instância de prefab que já tem overrides na cena. A Unity pergunta se você quer um prefab original ou uma variante; escolhendo variante, os overrides daquela instância viram os overrides da variante. É útil quando você ajustou um inimigo na fase, gostou e quer transformar aquilo num tipo novo.

Overrides: o que a variante muda e o que herda

Dê duplo clique em Enemy_Fast para abrir no Prefab Mode. Repare na Hierarchy: a raiz aparece como instância da base. Tudo que você mudar aqui é gravado como override da variante, e o Inspector marca em negrito com a linha azul na margem, igual a uma instância na cena.

Para conferir o que a variante sobrescreve, selecione a raiz e abra o dropdown Overrides no bloco Prefab do Inspector. A lista mostra cada campo e componente diferente da base. Dali você pode reverter tudo ou levar as mudanças para a base. Atenção a esse segundo botão: aplicar a partir da variante muda o prefab base e, por tabela, todas as outras variantes que herdam aquele campo.

O que costuma ficar na base e o que costuma virar override:

Fica na base (herda)Vira override na variante
Rigidbody2D, tipo de collider, layer, tagValores de vida, velocidade, dano
Script de comportamentoEscala, cor, sprite
Filhos comuns (sombra, barra de vida)Componentes extras só daquele tipo

Exemplo: inimigo base, rápido e tanque

Com as duas variantes criadas, configure:

Enemy_Fast

  • EnemyStats: maxHealth 12, moveSpeed 4.5, contactDamage 5.
  • Transform Scale 0.7.
  • Sprite Renderer Color num tom amarelado, para o jogador ler "rápido e frágil" de longe.

Enemy_Tank

  • EnemyStats: maxHealth 120, moveSpeed 1.2, contactDamage 25.
  • Transform Scale 1.5.
  • Rigidbody2D Mass 5, para ele empurrar e não ser empurrado.

Agora o teste que prova o valor da variante: abra Enemy_Base e aumente o CapsuleCollider2D. Volte para a cena com os três tipos e veja: os três ganharam o collider novo, porque nenhum sobrescreveu esse componente. Depois mude moveSpeed da base para 3. Só a base muda; Fast e Tank mantêm os valores próprios, porque os dois têm override nesse campo.

Por fim, o chefe. Clique com o botão direito em Enemy_Tank.prefab e escolha Create > Prefab Variant, criando Enemy_Boss. No Prefab Mode dele, mude a escala para 2.5, a vida para 600 e adicione um componente que só o chefe tem. Arquivo BossPhase.cs:

using UnityEngine;

public class BossPhase : MonoBehaviour
{
    [SerializeField] private SpriteRenderer spriteRenderer;
    [SerializeField] private Color enragedColor = Color.red;
    [SerializeField, Range(0f, 1f)] private float enrageThreshold = 0.3f;

    private bool enraged;

    public void OnHealthChanged(int current, int max)
    {
        if (enraged || max <= 0)
        {
            return;
        }

        float ratio = (float)current / max;
        if (ratio <= enrageThreshold)
        {
            enraged = true;
            spriteRenderer.color = enragedColor;
        }
    }
}

O componente aparece com o ícone de mais no Inspector da variante: é um componente adicionado, que não existe no Tank nem na base. O chefe herda do Tank a massa e o tipo de corpo, e do base o collider e o script de movimento. Para ligar o OnHealthChanged, exponha um evento no EnemyStats (por exemplo um UnityEvent<int, int>) e conecte pelo Inspector do chefe.

Montar a família de inimigos é a parte gostosa. O que costuma travar é o resto: fazer esses inimigos nascerem nas ondas certas, conversarem com HUD, som e pontuação, e o projeto continuar fácil de mexer quando o jogo cresce. É nesse ponto de juntar tudo num jogo que fecha que ter um caminho guiado faz diferença.

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

Nested prefabs e variants juntos

Variante e prefab aninhado se combinam. Suponha que todo inimigo tem um filho HealthBar, que é ele mesmo um prefab (HealthBar.prefab) com Canvas, imagem de fundo e imagem de preenchimento. Esse filho entra no Enemy_Base como prefab aninhado.

O resultado são três camadas de herança trabalhando juntas:

  • Trocar a cor do preenchimento em HealthBar.prefab atualiza a barra de todos os inimigos e de qualquer outro objeto que use a barra.
  • Mover a barra para cima em Enemy_Base atualiza Fast, Tank e Boss.
  • Subir mais a barra só no Enemy_Boss (porque ele é maior) vira override do Boss, sem afetar ninguém.

A pergunta para fazer antes de cada edição é "em qual nível essa mudança deveria valer?". Se vale para toda barra, edite o prefab da barra. Se vale para todo inimigo, edite a base. Se vale para um tipo, edite a variante. Essa disciplina é a mesma do princípio de composição que aparece em padrões de projeto para jogos.

Prefab Variant vs ScriptableObject para variar inimigos

As duas ferramentas resolvem "inimigos parecidos com números diferentes", e escolher errado gera retrabalho. O critério que uso:

Use Prefab Variant quando a variação é de estrutura ou visual. O chefe tem um componente a mais, o tanque tem outro collider, o voador não tem Rigidbody com gravidade. Isso é forma do objeto, e variant herda forma muito bem.

Use ScriptableObject quando a variação é só de dados. Se Fast, Tank e Boss diferem apenas em vida, velocidade e dano, um único prefab com um campo EnemyData e três assets de dados é mais simples: o game designer ajusta números numa ficha, compara as três lado a lado e não precisa abrir Prefab Mode. Esse formato também facilita o balanceamento por fórmula ou planilha, porque os números ficam em arquivos pequenos e previsíveis.

Use os dois quando o jogo cresce. Uma combinação comum: uma variante por "arquétipo" de estrutura (terrestre, voador, chefe) e um ScriptableObject por tipo de inimigo com os números. Assim você tem poucas variantes e muitos dados, em vez de quinze variantes onde cada uma sobrescreve três números.

Erros comuns: override preso e cadeia de variantes longa demais

Override preso. Você mexeu na velocidade da variante só para testar e esqueceu. Meses depois, ajusta a velocidade na base e aquela variante não acompanha. Antes de entregar uma variante, abra o dropdown Overrides e confirme que cada item da lista é intencional. O que for resto de teste, reverta.

Aplicar na base sem querer. No Prefab Mode da variante, o botão de aplicar ao pai leva o override para a base e muda todas as irmãs. Se o objetivo era mudar só o chefe, não aplique: deixe como override.

Cadeia longa demais. Base, depois Terrestre, depois Melee, depois Orc, depois Orc Elite, depois Orc Elite de Gelo. Seis níveis e ninguém sabe de onde vem a velocidade do último. Na prática, dois ou três níveis bastam. Se a cadeia passa disso, normalmente a diferença entre os elos é só número, e ela deveria virar dados.

Excluir a base. Variante sem base vira Missing Prefab. Mova e renomeie prefabs só pela janela Project, para o .meta acompanhar.

Próximo passo

Monte a família de quatro inimigos deste post num projeto de teste e faça a prova do collider: uma mudança na base chegando em todos, e uma mudança com override ficando só na variante. Depois experimente a versão híbrida, com um ScriptableObject de dados por tipo, e compare qual das duas você acha mais fácil de balancear. Se a parte de overrides em instância ainda está confusa, volte ao guia de prefab na Unity antes de seguir.

Perguntas frequentes

Qual a diferença entre prefab e Prefab Variant?

Um prefab comum é um molde independente. Uma Prefab Variant é um prefab que herda de outro (a base) e guarda só as diferenças, chamadas overrides. Mudanças na base chegam à variante em todos os campos que ela não sobrescreveu.

Posso criar uma variante de uma variante?

Pode. A Unity permite basear uma variante em qualquer prefab, inclusive em outra variante, formando uma cadeia. Funciona bem com dois ou três níveis; cadeias mais longas ficam difíceis de rastrear, porque um valor pode estar vindo de qualquer elo.

Como saber se um prefab é variante?

Na janela Project e na Hierarchy, a variante tem um ícone de cubo azul com um dos lados hachurado, diferente do cubo liso do prefab comum. No Inspector do asset, o bloco Prefab também mostra qual é a base.

Prefab Variant substitui ScriptableObject?

Não, eles resolvem coisas diferentes. Variant é boa quando o objeto muda de estrutura (componentes, filhos, visual). ScriptableObject é melhor quando só os números mudam e você quer editar dados sem abrir prefab. Muitos projetos usam os dois juntos.