Estou desenvolvendo meu primeiro jogo 2D no Unity e me deparei com o que parece ser uma pergunta importante.
Como lidar com dados entre cenas?
Parece haver respostas diferentes para isso:
Alguém mencionou o uso do PlayerPrefs , enquanto outras pessoas me disseram que isso deve ser usado para armazenar outras coisas, como brilho da tela e assim por diante.
Alguém me disse que a melhor maneira era certificar-se de escrever tudo em um jogo de salvamento toda vez que eu mudasse de cena e garantir que, quando a nova cena for carregada, obtenha as informações do jogo de salvamento novamente. Isso me pareceu um desperdício de desempenho. Eu estava errado?
A outra solução, que eu implementei até agora, é ter um objeto de jogo global que não seja destruído entre as cenas, manipulando todos os dados entre as cenas. Então, quando o jogo começa, eu carrego uma Cena Inicial em que este objeto está carregado. Depois que isso termina, ele carrega a primeira cena real do jogo, geralmente um menu principal.
Esta é a minha implementação:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class GameController : MonoBehaviour {
// Make global
public static GameController Instance {
get;
set;
}
void Awake () {
DontDestroyOnLoad (transform.gameObject);
Instance = this;
}
void Start() {
//Load first game scene (probably main menu)
Application.LoadLevel(2);
}
// Data persisted between scenes
public int exp = 0;
public int armor = 0;
public int weapon = 0;
//...
}
Este objeto pode ser tratado em minhas outras classes como esta:
private GameController gameController = GameController.Instance;
Embora isso tenha funcionado até agora, ele me apresenta um grande problema: se eu quiser carregar diretamente uma cena, digamos, por exemplo, o nível final do jogo, não posso carregá-lo diretamente, pois essa cena não contém esse objeto de jogo global .
Estou lidando com esse problema da maneira errada? Existem melhores práticas para esse tipo de desafio? Gostaria muito de ouvir suas opiniões, pensamentos e sugestões sobre este assunto.
obrigado
Uma maneira ideal de armazenar variáveis entre cenas é através de uma classe de gerenciador único. Criando uma classe para armazenar dados persistentes e configurando-a para
DoNotDestroyOnLoad()
, você pode garantir que ele seja imediatamente acessível e persista entre as cenas.Outra opção que você tem é usar a
PlayerPrefs
classe.PlayerPrefs
foi projetado para permitir que você salve dados entre sessões de reprodução , mas ainda servirá como um meio para salvar dados entre cenas .Usando uma classe singleton e
DoNotDestroyOnLoad()
O script a seguir cria uma classe singleton persistente. Uma classe singleton é uma classe projetada para executar apenas uma única instância ao mesmo tempo. Ao fornecer essa funcionalidade, podemos criar com segurança uma auto-referência estática, para acessar a classe de qualquer lugar. Isso significa que você pode acessar diretamente a classe
DataManager.instance
, incluindo quaisquer variáveis públicas dentro da classe.Você pode ver o singleton em ação, abaixo. Observe que, assim que executo a cena inicial, o objeto DataManager passa do cabeçalho específico da cena para o cabeçalho "DontDestroyOnLoad", na exibição da hierarquia.
Usando a
PlayerPrefs
classeO Unity foi construído em uma classe para gerenciar dados persistentes básicos chamados
PlayerPrefs
. Quaisquer dados confirmados noPlayerPrefs
arquivo persistirão nas sessões do jogo ; portanto, naturalmente, ele é capaz de persistir os dados nas cenas.O
PlayerPrefs
arquivo pode armazenar variáveis dos tiposstring
,int
efloat
. Quando inserimos valores noPlayerPrefs
arquivo, fornecemos um adicionalstring
como chave. Usamos a mesma chave para recuperar posteriormente nossos valores doPlayerPref
arquivo.Observe que tomo precauções adicionais ao manipular o
PlayerPrefs
arquivo:private static string
. Isso me permite garantir que estou sempre usando a chave certa e significa que, se eu precisar alterar a chave por qualquer motivo, não preciso garantir que altere todas as referências a ela.PlayerPrefs
arquivo no disco depois de gravá -lo. Provavelmente, isso não fará diferença se você não implementar a persistência de dados nas sessões de reprodução.PlayerPrefs
será salvo no disco durante o fechamento normal de um aplicativo, mas poderá não ser chamado naturalmente se o jogo travar.PlayerPrefs
, antes de tentar recuperar um valor associado a ele. Isso pode parecer uma verificação dupla inútil, mas é uma boa prática.Delete
método que limpa imediatamente oPlayerPrefs
arquivo. Se você não pretende incluir persistência de dados nas sessões de reprodução, considere chamar esse métodoAwake
. Ao limpar oPlayerPrefs
arquivo no início de cada jogo, você garante que todos os dados que se persistem desde a sessão anterior não é erroneamente tratados como os dados da atual sessão.Você pode ver
PlayerPrefs
em ação abaixo. Observe que, quando clico em "Salvar dados", estou chamando oSave
método diretamente e, quando clico em "Carregar dados", estou chamando oLoad
método diretamente . Sua própria implementação provavelmente varia, mas demonstra o básico.Como nota final, devo salientar que você pode expandir o básico
PlayerPrefs
, para armazenar tipos mais úteis. O JPTheK9 fornece uma boa resposta para uma pergunta semelhante , na qual eles fornecem um script para serializar matrizes na forma de cadeia de caracteres, para serem armazenadas em umPlayerPrefs
arquivo. Eles também nos apontam para o Wiki da Comunidade Unify , onde um usuário enviou umPlayerPrefsX
script mais abrangente para permitir o suporte a uma variedade maior de tipos, como vetores e matrizes.fonte