Voltar para o Blog
Quest Log

Trocar de Cena na Unity: SceneManager.LoadScene

Porta brilhante numa plataforma 2D levando a uma fase diferente, com o personagem prestes a entrar

Unity SceneManager.LoadScene na prática: troque de cena por nome e índice, crie porta para outra fase, recarregue a fase e resolva cena fora do Build Profile.

Ferramenta:UnityC#

Trocar de Cena na Unity: SceneManager.LoadScene

Para trocar de cena na Unity, use o unity scenemanager loadscene: SceneManager.LoadScene("Fase02") carrega a cena pelo nome, e SceneManager.LoadScene(2) carrega pelo índice. Antes disso, a cena precisa estar na Scene List do File > Build Profiles, ou a Unity mostra um erro e não carrega nada. Com essas duas peças você já tem menu levando para a fase, porta levando para a próxima e botão de tentar de novo.

Aqui você configura a lista de cenas no Unity 6.3 LTS, troca por nome e por índice, faz uma porta que leva o jogador para outra fase e aparece no ponto certo, recarrega e avança de fase, entende quando usar carregamento aditivo e resolve os dois erros que mais aparecem: cena não encontrada e cena escura.

Como trocar de cena na Unity

Uma cena é um arquivo .unity com uma hierarquia de objetos: uma fase, um menu, uma tela de créditos. Quando você troca de cena com LoadScene no modo padrão (Single), a Unity:

  1. Destrói todos os objetos da cena atual (exceto os marcados com DontDestroyOnLoad).
  2. Carrega a cena nova e cria os objetos dela.
  3. Chama Awake, OnEnable e Start nos objetos novos.

Tudo que estava na cena antiga some: a vida do jogador, as moedas coletadas, a posição. Se algo precisa sobreviver à troca, a solução é outra (objeto persistente ou dados estáticos), e fica para o fim do post.

Num jogo pequeno, a organização mais comum é uma cena por tela: MenuPrincipal, Fase01, Fase02, Creditos. Se você ainda está desenhando a estrutura do seu primeiro jogo, o post sobre como fazer um jogo do zero ajuda a decidir quantas telas ele precisa antes de criar cena à toa.

Adicionando cenas no Build Profile

A Unity só sabe carregar por código as cenas que estão na lista de build.

  1. Abra File > Build Profiles. Em tutoriais antigos, essa janela aparece como Build Settings.
  2. Na seção Scene List, arraste as cenas da janela Project para a lista. Outra opção: abra a cena e clique em Add Open Scenes.
  3. Arraste para reordenar. O número à direita de cada cena é o build index.
  4. Coloque o menu (ou a tela de abertura) em primeiro: o índice 0 é a cena que a build abre.

O checkbox ao lado de cada cena controla se ela entra na build. Desmarcada, ela continua na lista, mas não pode ser carregada. Para tirar da lista de vez, clique com o botão direito e use Remove Selection.

SceneManager.LoadScene por nome e por índice

Todo script que troca de cena precisa do namespace UnityEngine.SceneManagement.

Arquivo TrocadorDeCena.cs:

using UnityEngine;
using UnityEngine.SceneManagement;

public class TrocadorDeCena : MonoBehaviour
{
    [SerializeField] private string nomeDaCena = "Fase01";
    [SerializeField] private int indiceDaCena = 1;

    public void CarregarPorNome()
    {
        SceneManager.LoadScene(nomeDaCena);
    }

    public void CarregarPorIndice()
    {
        SceneManager.LoadScene(indiceDaCena);
    }
}

Por nome é mais legível e não quebra se você reordenar a lista. Quebra se você renomear o arquivo da cena. Por índice não quebra com renomeação, mas muda de destino se você reordenar a lista. Uma regra que funciona: use nome para destinos fixos (menu, créditos) e índice para sequência de fases (a próxima é sempre a seguinte na lista).

Um detalhe de comportamento: o LoadScene não troca a cena na hora exata da chamada. A troca acontece no começo do frame seguinte. O código que vem depois da chamada, no mesmo método, ainda roda. Se você chama LoadScene e logo depois mexe num objeto da cena atual, isso funciona, mas é um sinal de que a lógica está na ordem errada.

Porta ou trigger que leva para outra fase

A porta é um objeto com um Box Collider 2D marcado como Is Trigger e este script. O jogador precisa da tag Player e de um Rigidbody2D (para 3D, troque para OnTriggerEnter e Collider).

Arquivo PortaDeFase.cs:

using UnityEngine;
using UnityEngine.SceneManagement;

public class PortaDeFase : MonoBehaviour
{
    [SerializeField] private string cenaDestino = "Fase02";
    [SerializeField] private string idDaEntradaNoDestino = "PortaOeste";

    private bool usada;

    private void OnTriggerEnter2D(Collider2D outro)
    {
        if (usada || !outro.CompareTag("Player"))
        {
            return;
        }

        usada = true;
        PontoDeEntrada.IdDestino = idDaEntradaNoDestino;
        SceneManager.LoadScene(cenaDestino);
    }
}

O usada impede que dois colliders do jogador (corpo e pés, por exemplo) disparem a troca duas vezes no mesmo frame. O idDaEntradaNoDestino resolve o problema que toda porta tem: na fase nova, o jogador aparece onde? Sem isso, ele nasce sempre no ponto inicial da fase, mesmo quando volta pela porta do outro lado.

Na cena de destino, cada entrada é um objeto vazio com este script, posicionado onde o jogador deve aparecer:

Arquivo PontoDeEntrada.cs:

using UnityEngine;

public class PontoDeEntrada : MonoBehaviour
{
    public static string IdDestino { get; set; }

    [SerializeField] private string id = "PortaOeste";
    [SerializeField] private Transform jogador;

    private void Start()
    {
        if (string.IsNullOrEmpty(IdDestino) || IdDestino != id)
        {
            return;
        }

        jogador.position = transform.position;
        IdDestino = null;
    }
}

A propriedade estática sobrevive à troca de cena (variáveis estáticas não pertencem a nenhuma cena), então a porta da fase antiga consegue deixar um recado para a fase nova. Com isso, um mapa de várias salas interligadas funciona nos dois sentidos. Para desenhar como essas salas se conectam e onde ficam as entradas, o post de design de levels é um bom complemento.

Cada peça aqui é pequena. O que pesa é quando a troca de cena encontra o resto do jogo: o jogador que precisa chegar com a vida certa, a música que não pode reiniciar, a câmera que precisa achar o jogador novo, o save que precisa gravar antes da troca. Fazer isso funcionar num jogo inteiro, sem alguém revisando o seu projeto, é onde muita gente empaca.

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

Recarregar a cena atual e próxima fase

Tentar de novo e avançar de fase usam o índice da cena ativa.

Arquivo ControleDeFase.cs:

using UnityEngine;
using UnityEngine.SceneManagement;

public class ControleDeFase : MonoBehaviour
{
    [SerializeField] private string cenaDoMenu = "MenuPrincipal";

    public void ReiniciarFase()
    {
        int indiceAtual = SceneManager.GetActiveScene().buildIndex;
        SceneManager.LoadScene(indiceAtual);
    }

    public void ProximaFase()
    {
        int proximoIndice = SceneManager.GetActiveScene().buildIndex + 1;

        if (proximoIndice < SceneManager.sceneCountInBuildSettings)
        {
            SceneManager.LoadScene(proximoIndice);
        }
        else
        {
            SceneManager.LoadScene(cenaDoMenu);
        }
    }
}

GetActiveScene().buildIndex dá o índice da cena atual na lista. sceneCountInBuildSettings dá quantas cenas a build tem, para o ProximaFase voltar ao menu depois da última em vez de tentar carregar um índice que não existe.

Recarregar a cena volta tudo ao estado inicial: inimigos, moedas, portas. As exceções são variáveis estáticas e objetos com DontDestroyOnLoad, que continuam com o valor de antes. Se o jogador reinicia a fase e o contador de moedas não zera, procure um static esquecido.

Carregamento aditivo: quando usar

LoadScene aceita um segundo parâmetro, o modo. Com LoadSceneMode.Additive, a cena nova é carregada junto com a atual, sem destruir nada:

SceneManager.LoadScene("HUD", LoadSceneMode.Additive);

Usos que valem a pena:

  • UI separada da fase: uma cena HUD carregada por cima de cada fase. A UI fica num arquivo só e não precisa ser copiada em toda fase.
  • Mundo em pedaços: salas ou trechos carregados e descarregados conforme o jogador anda, com SceneManager.LoadSceneAsync e SceneManager.UnloadSceneAsync.
  • Cena de sistemas: uma cena com gerenciadores (áudio, save) carregada uma vez, com as fases entrando e saindo em volta dela.

Com várias cenas abertas, uma delas é a cena ativa: é nela que objetos criados com Instantiate nascem e é a iluminação dela que vale. Defina com SceneManager.SetActiveScene. Para um primeiro jogo, o modo Single resolve. Aditivo começa a valer quando você sente a dor de copiar a mesma UI em dez fases.

Para fases grandes, que demoram para carregar, troque o LoadScene por LoadSceneAsync com uma tela de loading. O post de tela de loading na Unity mostra como, incluindo o detalhe da barra que para em 90%.

Erros comuns: cena não encontrada e luz escura após trocar

Cena não encontrada. O Console avisa que a cena não pode ser carregada porque não está na build. Abra File > Build Profiles, confira se ela está na Scene List e se o checkbox está marcado. Confira também o nome: é sensível a maiúsculas e precisa ser exatamente o nome do arquivo, sem .unity.

Cena escura depois de trocar. Quando a cena é carregada por código, ela usa só os dados de luz salvos com ela. Se esses dados nunca foram gerados, a cena pode chegar sem luz ambiente ou com reflexos errados, mesmo parecendo certa quando você a abre no editor. No Unity 6 o editor não faz esse bake sozinho em projeto novo. Abra a cena, vá em Window > Rendering > Lighting e clique em Generate Lighting. A Unity salva um asset de iluminação junto com a cena.

Troca acontece duas vezes. Dois colliders do jogador tocaram o trigger. O usada da porta evita.

Objeto some ao trocar de cena. Esse é o comportamento padrão do modo Single. Para manter um objeto vivo, ele precisa de DontDestroyOnLoad, com os cuidados de não duplicar quando a cena dele carrega de novo.

Jogador aparece na posição errada. O PontoDeEntrada roda no Start; se outro script reposiciona o jogador depois (um checkpoint, por exemplo), ele sobrescreve. Centralize quem decide a posição inicial.

Próximo passo: dados que sobrevivem à troca

Com a troca de cena dominada, o próximo problema aparece sozinho: a vida, as moedas e a música que precisam continuar entre as fases. Pratique fazendo um contador de moedas que persiste entre três fases e zera ao voltar para o menu. A solução passa por objeto persistente com DontDestroyOnLoad ou por uma cena de sistemas carregada uma vez, os dois caminhos que a próxima leitura sobre persistência entre cenas aprofunda.

Perguntas frequentes

Como trocar de cena na Unity por código?

Adicione using UnityEngine.SceneManagement no script e chame SceneManager.LoadScene("NomeDaCena") ou SceneManager.LoadScene(indice). A cena precisa estar na Scene List do Build Profiles.

Onde ficam as cenas da build no Unity 6?

Em File > Build Profiles, na seção Scene List. A ordem da lista define o índice de cada cena, e a cena de índice 0 é a primeira que a build abre. Cena com o checkbox desmarcado fica fora da build.

Como recarregar a fase atual na Unity?

Use SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex). Isso destrói e recria todos os objetos da cena, voltando tudo ao estado inicial, exceto objetos marcados com DontDestroyOnLoad e variáveis estáticas.

Por que a cena fica escura depois de trocar de cena na Unity?

Normalmente a cena não tem dados de iluminação gerados e dependia do que o editor calculava ao abri-la. Abra a cena, vá em Window > Rendering > Lighting e clique em Generate Lighting para salvar a iluminação junto com a cena.