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.
using UnityEngine;
/// <summary>Manages data for persistance between levels.</summary>
public class DataManager : MonoBehaviour
{
/// <summary>Static reference to the instance of our DataManager</summary>
public static DataManager instance;
/// <summary>The player's current score.</summary>
public int score;
/// <summary>The player's remaining health.</summary>
public int health;
/// <summary>The player's remaining lives.</summary>
public int lives;
/// <summary>Awake is called when the script instance is being loaded.</summary>
void Awake()
{
// If the instance reference has not been set, yet,
if (instance == null)
{
// Set this instance as the instance reference.
instance = this;
}
else if(instance != this)
{
// If the instance reference has already been set, and this is not the
// the instance reference, destroy this game object.
Destroy(gameObject);
}
// Do not destroy this object, when we load a new scene.
DontDestroyOnLoad(gameObject);
}
}
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
classe
O Unity foi construído em uma classe para gerenciar dados persistentes básicos chamadosPlayerPrefs
. Quaisquer dados confirmados no PlayerPrefs
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 tipos string
, int
e float
. Quando inserimos valores no PlayerPrefs
arquivo, fornecemos um adicional string
como chave. Usamos a mesma chave para recuperar posteriormente nossos valores do PlayerPref
arquivo.
using UnityEngine;
/// <summary>Manages data for persistance between play sessions.</summary>
public class SaveManager : MonoBehaviour
{
/// <summary>The player's name.</summary>
public string playerName = "";
/// <summary>The player's score.</summary>
public int playerScore = 0;
/// <summary>The player's health value.</summary>
public float playerHealth = 0f;
/// <summary>Static record of the key for saving and loading playerName.</summary>
private static string playerNameKey = "PLAYER_NAME";
/// <summary>Static record of the key for saving and loading playerScore.</summary>
private static string playerScoreKey = "PLAYER_SCORE";
/// <summary>Static record of the key for saving and loading playerHealth.</summary>
private static string playerHealthKey = "PLAYER_HEALTH";
/// <summary>Saves playerName, playerScore and
/// playerHealth to the PlayerPrefs file.</summary>
public void Save()
{
// Set the values to the PlayerPrefs file using their corresponding keys.
PlayerPrefs.SetString(playerNameKey, playerName);
PlayerPrefs.SetInt(playerScoreKey, playerScore);
PlayerPrefs.SetFloat(playerHealthKey, playerHealth);
// Manually save the PlayerPrefs file to disk, in case we experience a crash
PlayerPrefs.Save();
}
/// <summary>Saves playerName, playerScore and playerHealth
// from the PlayerPrefs file.</summary>
public void Load()
{
// If the PlayerPrefs file currently has a value registered to the playerNameKey,
if (PlayerPrefs.HasKey(playerNameKey))
{
// load playerName from the PlayerPrefs file.
playerName = PlayerPrefs.GetString(playerNameKey);
}
// If the PlayerPrefs file currently has a value registered to the playerScoreKey,
if (PlayerPrefs.HasKey(playerScoreKey))
{
// load playerScore from the PlayerPrefs file.
playerScore = PlayerPrefs.GetInt(playerScoreKey);
}
// If the PlayerPrefs file currently has a value registered to the playerHealthKey,
if (PlayerPrefs.HasKey(playerHealthKey))
{
// load playerHealth from the PlayerPrefs file.
playerHealth = PlayerPrefs.GetFloat(playerHealthKey);
}
}
/// <summary>Deletes all values from the PlayerPrefs file.</summary>
public void Delete()
{
// Delete all values from the PlayerPrefs file.
PlayerPrefs.DeleteAll();
}
}
Observe que tomo precauções adicionais ao manipular o PlayerPrefs
arquivo:
- Eu salvei cada chave como um
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.
- Eu salvo o
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.
- Na verdade, verifico se cada chave existe no
PlayerPrefs
, antes de tentar recuperar um valor associado a ele. Isso pode parecer uma verificação dupla inútil, mas é uma boa prática.
- Eu tenho um
Delete
método que limpa imediatamente o PlayerPrefs
arquivo. Se você não pretende incluir persistência de dados nas sessões de reprodução, considere chamar esse método Awake
. Ao limpar o PlayerPrefs
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 o Save
método diretamente e, quando clico em "Carregar dados", estou chamando o Load
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 um PlayerPrefs
arquivo. Eles também nos apontam para o Wiki da Comunidade Unify , onde um usuário enviou um PlayerPrefsX
script mais abrangente para permitir o suporte a uma variedade maior de tipos, como vetores e matrizes.