Manter entre Cenas
Parte da seção Criando Jogos de Verdade do Journey de Unity da Coddy. Lição 20 de 60.
Carregar uma cena destrói todos os objetos da cena anterior, mas algumas coisas precisam durar o jogo inteiro, como as moedas que um jogador leva de um nível para outro. DontDestroyOnLoad(gameObject) move um objeto da cena dele para uma cena própria, chamada DontDestroyOnLoad na Hierarchy ao clicar em “Jogar”, que nunca é afetada pelos carregamentos. Isso funciona apenas em um objeto raiz: em um objeto filho, o Unity registra um aviso e não mantém nada. Os filhos do objeto mantido vêm junto, mas os objetos para os quais ele apenas aponta, não: depois do carregamento, um campo que apontava para um objeto da cena anterior contém um objeto destruído, que é igual a null.
public class GameSession : MonoBehaviour
{
public static GameSession Instance;
public int coins;
void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
}Este GameSession fica na cena Menu. Ao clicar em “Jogar”, o jogo vai de Menu para Level1 e, depois, volta para Menu, que cria todos os seus objetos novamente, incluindo um novo GameSession, enquanto o objeto mantido continua lá. Sem a verificação em Awake, haveria dois, e o recém-criado assumiria Instance com 0 moedas. Com ela, o recém-criado encontra Instance já definido, destrói a si mesmo e para, e a sessão que passou pelos níveis permanece.
O return é importante porque Destroy aguarda até o fim do quadro. Sem ele, o restante de Awake ainda seria executado para o recém-criado: Instance = this; faria com que todos os scripts apontassem para um objeto prestes a ser destruído.
Desafio
FácilMantenha um único relógio da partida funcionando durante o carregamento de cada cena.
- Em
Awake(), seInstance != null, chameDestroy(gameObject);ereturn;. Caso contrário, definaInstancee chameDontDestroyOnLoad(gameObject);. - O carregamento destrói o texto do nível anterior, então, em
Update(), antes da linha do texto, quandoclockText == null, definaclockText = GameObject.Find("ClockText").GetComponent<TMP_Text>();.
Pressione “Jogar”, vá para Level2 e volte: um único relógio continua contando. Depois, pressione “Verificar”.
Experimente você mesmo
using UnityEngine;
using TMPro;
public class RunClock : MonoBehaviour
{
public static RunClock Instance;
public TMP_Text clockText;
private float seconds;
void Awake()
{
Instance = this;
}
void Update()
{
seconds += Time.deltaTime;
clockText.text = "Time: " + seconds.ToString("0.0");
}
public void Split()
{
Debug.Log("Split: " + seconds.ToString("0.0"));
}
}
Todas as lições de Criando Jogos de Verdade
1Texto na tela
Canvas e textoExiba a pontuaçãoFormate númerosUm cronômetro regressivoRevisão: velocímetro4Cenas e Fases
Carregar uma CenaReiniciar a FasePróxima FaseManter entre CenasRevisão: Seleção de Fases2Botões e telas
Botões e onClickLambdasConectando no InspectorPainéis ligados e desligadosBarras de vidaRevisão: Loja de melhorias5Salvando com PlayerPrefs
Salvar um númeroCarregar com um valor padrãoRecordeSalvar configuraçõesRevisão: Moedas no bancoPratique por conta própria: Playground de Unity