Manter entre Cenas
Parte da seção Criando jogos de verdade do Journey de Unity da Coddy. Lição 20 de 56.
Carregar uma cena destrói todos os objetos da cena anterior, mas algumas coisas precisam durar o jogo todo, como as moedas que um jogador leva de um nível para outro. DontDestroyOnLoad(gameObject) move um objeto para fora da cena dele, para uma cena própria, chamada DontDestroyOnLoad na Hierarchy durante o Play, que nunca é afetada pelo carregamento. 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: após o carregamento, um campo que apontava para um objeto da cena anterior mantém um objeto destruído, que é igual a null em uma comparação.
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. O Play percorre Menu, Level1 e depois volta para Menu, e a cena Menu cria todos os seus objetos novamente, incluindo um novo GameSession, enquanto o objeto mantido ainda está 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 frame. Sem ele, o restante de Awake ainda é executado para o recém-criado: Instance = this; apontaria todos os scripts para um objeto prestes a ser destruído.
Desafio
FácilUm cronômetro de speedrun. O objeto RunClock em Level1 conta os segundos da execução inteira e registra um split sempre que um nível é concluído. O Goal dourado de Level1 carrega Level2, cujo objetivo carrega Level1 novamente, e cada objetivo chama RunClock.Instance.Split() primeiro. Cada nível tem seu próprio HUD com um ClockText; o Inspector atribui ao RunClock o que está em Level1. As setas movem o Player. Altere RunClock.cs para que:
- o cronômetro continue funcionando durante o carregamento de todas as cenas, sem recomeçar;
- o tempo sempre apareça no
ClockTextdo nível que está aberto, comoTime: 12.3; - ao voltar para Level1, que tem seu próprio RunClock, ainda haja apenas um cronômetro: aquele que está funcionando, e
RunClock.Instanceseja esse.
Pressione Play, vá para Level2 e volte, conclua Level1 novamente e, em seguida, clique em Check.
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"));
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
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 Fases10Projeto: Jogo de Plataforma 3D
O PercursoPlataformas Móveis2Botõ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 banco