Voltar para o Blog
Quest Log

Jogo 2.5D na Unity: Sprites 2D em Mundo 3D

Personagem em pixel art plano andando num cenário 3D de vila com casas, árvores e luz do fim de tarde projetando sombras

Como fazer um jogo 2.5D na Unity: sprites 2D em cenário 3D, billboard que encara a câmera, sombra de sprite no URP, câmera em perspectiva e física 3D ou 2D.

Ferramenta:UnityC#

Jogo 2.5D na Unity: Sprites 2D em Mundo 3D

Como fazer um jogo 2.5D na Unity no estilo HD-2D: você coloca personagens desenhados em 2D dentro de um cenário 3D, com câmera em perspectiva, sprites que giram para encarar a câmera (billboard), sombras projetadas no chão e iluminação real da URP. Este guia mostra cada etapa no Unity 6.3 LTS: configuração de câmera, importação de sprite, billboard em C#, o jeito confiável de fazer o sprite projetar sombra, e a decisão entre física 3D e física 2D com profundidade falsa.

O resultado é um personagem em pixel art andando por uma vila em 3D, com sombra no chão e luz do sol, a base visual de jogos como Octopath Traveler e de muitos indies que misturam as duas dimensões.

O que é 2.5D (e os tipos)

"2.5D" cobre coisas diferentes, e escolher o tipo certo antes de começar evita retrabalho:

  • Jogabilidade 2D, visual 3D. O personagem só anda para os lados e pula, mas tudo é modelo 3D com câmera em perspectiva. Exemplos: plataformas de lado feitos com modelos 3D. Na Unity, é um jogo 3D com o eixo Z travado.
  • Visual 2D, mundo 3D. Personagens e objetos são sprites planos, o cenário é 3D, e o jogador anda em profundidade. É o estilo HD-2D e o de jogos com "papel recortado". Este é o foco do post.
  • Isométrico. Arte 2D desenhada em ângulo para simular profundidade, com câmera ortográfica. Na Unity, normalmente vive no pipeline 2D com Tilemap isométrico.

O tipo 2 é o que mais confunde, porque mistura sistemas pensados para 2D (sprites) com sistemas pensados para 3D (luz, sombra, física). Para decidir se vale a pena o estilo misto no seu projeto, o post arte 2D ou 3D para jogo indie compara custo de produção dos dois lados, e o guia de HD-2D: pixel art em 3D foca a parte de arte.

Configurar câmera e cena

Crie o projeto com o template Universal 3D. O 2D template usa o Renderer 2D, que não tem as sombras de luz 3D que você quer aqui.

Câmera:

  • Projection: Perspective.
  • Field of View: entre 25 e 35. Um FOV baixo achata a perspectiva e dá aquele visual de maquete, típico do HD-2D. O padrão de 60 distorce os sprites nas bordas.
  • Rotação X: entre 25 e 35 graus, olhando para baixo.
  • Distância: com FOV baixo, a câmera fica mais longe (12 a 18 unidades do personagem) para enquadrar a mesma área.

Cena: um Plane para o chão, alguns cubos como casas e árvores (greybox), uma Directional Light com rotação X de 50 graus e Shadow Type: Soft Shadows. No asset da URP (em Edit > Project Settings > Quality, o Render Pipeline Asset ativo), confira se Main Light > Cast Shadows está ligado e ajuste Shadows > Max Distance para algo como 40; distância de sombra grande demais deixa a sombra borrada perto da câmera.

Para o visual de maquete, acrescente no Volume global um override de Depth Of Field em modo Bokeh, focado na distância do personagem. As bordas desfocadas são metade da cara do HD-2D.

Sprites 2D em mundo 3D na Unity

Importe o sprite do personagem e configure no Inspector da textura:

  • Texture Type: Sprite (2D and UI).
  • Pixels Per Unit: defina para que o personagem tenha a altura certa no mundo. Um sprite de 32 pixels de altura com PPU 20 fica com 1,6 unidade, a altura de uma pessoa se 1 unidade é 1 metro.
  • Filter Mode: Point (no filter), para pixel art não borrar.
  • Compression: None.

Existem dois jeitos de colocar esse sprite no mundo 3D:

Sprite Renderer. Arraste o sprite para a cena. Funciona, anima com o Animator como em qualquer jogo 2D e é o caminho mais rápido. O material padrão é o Sprite-Lit-Default. O limite: o Sprite Renderer não oferece opção de projetar sombra no Inspector, e os materiais de sprite não têm o passe de sombra que a URP usa para desenhar o objeto no mapa de sombras.

Quad com material Lit. Um GameObject > 3D Object > Quad com um material URP Lit que usa o sprite como Base Map. Ligue Alpha Clipping (Threshold 0,5), Render Face: Both e, no Mesh Renderer, Cast Shadows: On (ou Two Sided). O quad recebe luz 3D, projeta sombra recortada no formato do sprite e escreve no buffer de profundidade. Para animar, troque o offset e o tiling da textura de uma sprite sheet por script, ou use um Sprite Renderer só para a animação e copie o sprite atual para o material.

Para o personagem principal, o quad com Lit dá o melhor resultado visual. Para objetos pequenos e numerosos (moedas, plantas), o Sprite Renderer com uma sombra falsa (um quad escuro e redondo no chão) é mais barato e quase ninguém nota a diferença.

Billboard: sprite encarando a câmera

Num mundo 3D, a câmera pode girar ou o personagem pode passar ao lado dela. Sem billboard, o sprite fica de lado e vira uma linha fina. O billboard gira o sprite para sempre encarar a câmera.

Arquivo Billboard.cs:

using UnityEngine;

public class Billboard : MonoBehaviour
{
    public enum Mode { Full, YAxisOnly }

    [SerializeField] private Mode mode = Mode.YAxisOnly;

    private Transform cam;

    private void Start()
    {
        cam = Camera.main.transform;
    }

    private void LateUpdate()
    {
        if (mode == Mode.Full)
        {
            transform.rotation = cam.rotation;
            return;
        }

        Vector3 forward = cam.forward;
        forward.y = 0f;
        if (forward.sqrMagnitude < 0.0001f) return;
        transform.rotation = Quaternion.LookRotation(forward.normalized, Vector3.up);
    }
}

Dois modos, com usos diferentes:

  • Full copia a rotação inteira da câmera. O sprite fica sempre paralelo à tela, inclusive inclinado quando a câmera olha de cima. Bom para partículas, ícones e efeitos.
  • YAxisOnly (cilíndrico) gira só em torno do eixo vertical. O sprite continua em pé no chão, como um recorte de papelão. É o certo para personagens, árvores e objetos que precisam "pisar" no chão, e é o que mantém a sombra coerente: um sprite deitado projetaria uma sombra esmagada.

O código copia a direção da câmera, não aponta para a posição dela. Apontar para a posição (LookAt) faz sprites nas bordas da tela girarem em ângulos diferentes, e numa fila de árvores cada uma fica virada para um lado. Copiar a direção mantém todos paralelos. Rode sempre em LateUpdate, depois que a câmera já se moveu no frame.

Com câmera, sprite e billboard, o visual já existe. Transformar isso num jogo pede sombra coerente, animação por direção, colisão com o cenário, interação, interface, áudio e uma build que roda bem, e é nessa costura entre sistemas 2D e 3D que muitos projetos 2.5D param, porque cada decisão de arte afeta a de código.

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

Sombras de sprite no URP

Com o quad em Lit e Alpha Clipping, a sombra aparece recortada no formato do personagem. Três ajustes resolvem os problemas que aparecem em seguida:

Sombra girando com o billboard. A sombra é desenhada do ponto de vista da luz, mas o quad está virado para a câmera. Quando a câmera e a luz estão em ângulos muito diferentes, a sombra fica fina. Escolha a direção da luz próxima da direção da câmera (luz vindo de trás e um pouco do lado da câmera) e o efeito some. É o que os jogos HD-2D fazem.

Sombra descolada do pé. O pivô do quad está no centro. Coloque o quad como filho de um objeto vazio, com o pé do personagem na origem do pai (o quad sobe metade da altura). O pai é quem fica no chão e recebe o script de movimento.

Acne de sombra (listras no próprio sprite). Na luz direcional, aumente levemente Depth Bias e Normal Bias nas configurações de sombra da luz, ou desligue Receive Shadows no material do personagem se ele não precisa receber sombra de outros objetos.

Se você usa Sprite Renderer, é possível ligar shadowCastingMode por script, porque a propriedade existe na classe base Renderer. Mas sem um material que tenha passe de sombra, nada aparece. Por isso o quad com Lit é o caminho recomendado.

Física: 3D com sprite ou 2D com profundidade fake

A decisão de física depende de como o personagem se move.

Física 3D com sprite. O personagem anda no plano XZ, para frente, para trás e para os lados. Ele tem Rigidbody com Freeze Rotation nos três eixos e um CapsuleCollider do tamanho do corpo. O cenário usa colliders 3D normais. Essa é a opção do estilo HD-2D e de jogos de exploração.

Física 2D com profundidade falsa. O jogo é de lado (plataforma ou beat 'em up de corredor), a física 2D roda no plano XY, e a profundidade é só visual: o cenário 3D fica atrás, a câmera em perspectiva dá o parallax de graça. Em beat 'em ups, a "profundidade" em que o personagem anda é o eixo Y da física 2D, e a ordem de desenho segue a posição Y.

O que não funciona é misturar: um personagem com Rigidbody2D não colide com um BoxCollider 3D. Escolha uma física e use só ela.

Jogo 2.5D na Unity: movimento e colisão

Movimento com física 3D, Input System e o sprite virando para o lado do movimento.

Arquivo Character25D.cs (no objeto pai, com Rigidbody e CapsuleCollider):

using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(Rigidbody))]
public class Character25D : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 4f;
    [SerializeField] private Transform visual;
    [SerializeField] private Animator animator;

    private Rigidbody rb;
    private InputAction moveAction;
    private Transform cam;
    private float facing = 1f;

    private void Awake()
    {
        rb = GetComponent<Rigidbody>();
        rb.constraints = RigidbodyConstraints.FreezeRotation;
        moveAction = InputSystem.actions.FindAction("Player/Move");
        cam = Camera.main.transform;
    }

    private void FixedUpdate()
    {
        Vector2 input = Vector2.ClampMagnitude(moveAction.ReadValue<Vector2>(), 1f);

        Vector3 camForward = cam.forward;
        camForward.y = 0f;
        camForward.Normalize();
        Vector3 camRight = cam.right;
        camRight.y = 0f;
        camRight.Normalize();

        Vector3 move = camRight * input.x + camForward * input.y;
        rb.linearVelocity = new Vector3(move.x * moveSpeed, rb.linearVelocity.y, move.z * moveSpeed);

        if (Mathf.Abs(input.x) > 0.1f)
        {
            facing = Mathf.Sign(input.x);
        }
    }

    private void LateUpdate()
    {
        Vector3 scale = visual.localScale;
        scale.x = Mathf.Abs(scale.x) * facing;
        visual.localScale = scale;

        if (animator != null)
        {
            animator.SetFloat("Speed", new Vector2(rb.linearVelocity.x, rb.linearVelocity.z).magnitude);
        }
    }
}

O movimento é relativo à câmera: "para cima" no controle é "para longe da câmera" no mundo, seja qual for a rotação dela. O sprite vira espelhando a escala X do quad filho (no Sprite Renderer, use flipX). O pai não gira nunca, só se move; quem gira é o filho visual, com o Billboard.

Separar pai (física) e filho (visual) é o que deixa o sistema estável. O billboard pode girar o visual à vontade sem mexer na colisão, e a cápsula fica sempre em pé.

Erros comuns: sprite cortado, sombra sumindo

  • Sprite cortado pelo chão ou por paredes. O quad atravessa a geometria quando o billboard gira. Afaste o collider das paredes ou use o modo YAxisOnly, que mantém o sprite em pé.
  • Sombra sumindo. Sprite Renderer com material de sprite, sem passe de sombra. Use quad com Lit e Alpha Clipping.
  • Sombra some longe da câmera. Max Distance de sombra no asset da URP baixa demais.
  • Sprite borrado. Filter Mode em Bilinear. Use Point para pixel art.
  • Borda branca ou preta em volta do sprite. Compressão ligada ou Alpha Clipping desligado com material opaco.
  • Sprites piscando na frente um do outro. Transparência sem escrita de profundidade. Com Alpha Clipping em material opaco, o buffer de profundidade ordena os sprites corretamente.
  • Personagem tombando. Faltou travar rotação no Rigidbody.

Próximo passo

Monte uma cena de vila com 5 casas de cubo, 10 árvores em Sprite Renderer com sombra falsa e o personagem em quad com sombra real. Depois, acrescente uma câmera Cinemachine que segue o personagem com leve atraso e teste girar a câmera 45 graus: o billboard e o movimento relativo à câmera precisam continuar funcionando. Se ainda está escolhendo ferramenta para projetos com mais 3D, compare as opções no guia de melhor engine para jogos 3D.

Perguntas frequentes

O que é um jogo 2.5D?

É um jogo que mistura elementos 2D e 3D. Pode ser jogabilidade 2D com gráficos 3D (um jogo de plataforma de lado feito com modelos 3D) ou o contrário, personagens 2D desenhados andando num mundo 3D, como no estilo HD-2D. Isométricos também entram no termo quando simulam profundidade com arte 2D.

Como fazer um sprite olhar sempre para a câmera na Unity?

Num LateUpdate, copie a rotação da câmera para o sprite (billboard completo) ou gire o sprite só no eixo Y na direção da câmera (billboard cilíndrico). O cilíndrico é o mais usado em personagens, porque o sprite não deita quando a câmera olha de cima.

Sprite projeta sombra no URP 3D?

O Sprite Renderer não mostra opção de sombra no Inspector, e os materiais de sprite padrão não têm passe de sombra. O caminho confiável é desenhar o personagem num Quad com material URP Lit, Alpha Clipping ligado e Cast Shadows em On. A alternativa simples é uma sombra falsa: um círculo escuro no chão sob o personagem.

Jogo 2.5D na Unity deve usar física 2D ou 3D?

Se o personagem anda em profundidade (para frente e para trás no cenário), use física 3D. Se o jogo é de lado e a profundidade é só visual, física 2D é mais simples e leve. Misturar as duas no mesmo objeto não funciona, porque colliders 2D e 3D não interagem.