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.
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.



