Идеальный способ хранения переменных между сценами - через класс синглтон-менеджера. Создав класс для хранения постоянных данных и установив для него класс DoNotDestroyOnLoad()
, вы можете обеспечить его немедленный доступ и его сохранение между сценами.
Другой вариант - использовать PlayerPrefs
класс. PlayerPrefs
предназначен для сохранения данных между сеансами воспроизведения , но все равно будет служить средством сохранения данных между сценами .
Используя одноэлементный класс и DoNotDestroyOnLoad()
Следующий скрипт создает постоянный одноэлементный класс. Класс Singleton - это класс, предназначенный для одновременного запуска только одного экземпляра. Предоставляя такие функциональные возможности, мы можем безопасно создавать статические ссылки на себя, чтобы получить доступ к классу из любого места. Это означает, что вы можете напрямую обращаться к классу DataManager.instance
, включая любые открытые переменные внутри класса.
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);
}
}
Вы можете увидеть синглтон в действии, ниже. Обратите внимание, что как только я запускаю начальную сцену, объект DataManager перемещается из заголовка, относящегося к сцене, в заголовок «DontDestroyOnLoad» в представлении иерархии.
Используя PlayerPrefs
класс
Unity имеет встроенный класс для управления основными постоянными даннымиPlayerPrefs
. Любые данные, сохраненные в PlayerPrefs
файле, будут сохраняться в течение игровых сеансов , поэтому, естественно, они способны сохранять данные в разных сценах.
PlayerPrefs
Файл может хранить переменные типов string
, int
и float
. Когда мы вставляем значения в PlayerPrefs
файл, мы предоставляем дополнительный string
ключ. Мы используем тот же ключ для последующего извлечения наших значений из PlayerPref
файла.
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();
}
}
Обратите внимание, что я принимаю дополнительные меры предосторожности при работе с PlayerPrefs
файлом:
- Я сохранил каждый ключ как
private static string
. Это позволяет мне гарантировать, что я всегда использую правильный ключ, и это означает, что если мне по какой-либо причине придется менять ключ, мне не нужно обязательно менять все ссылки на него.
- Я сохраняю
PlayerPrefs
файл на диск после записи на него. Это, вероятно, не будет иметь значения, если вы не реализуете постоянство данных во время сеансов воспроизведения. PlayerPrefs
будет сохранить на диск во время обычного приложения близко, но он не может естественно назвать , если ваша игра вылетает.
- Я на самом деле проверяю, что каждый ключ существует в
PlayerPrefs
, прежде чем пытаться получить значение, связанное с ним. Это может показаться бессмысленной двойной проверкой, но это хорошая практика.
- У меня есть
Delete
метод, который сразу стирает PlayerPrefs
файл. Если вы не намерены включать постоянство данных в сеансы воспроизведения, вы можете включить этот метод Awake
. Сняв PlayerPrefs
файл в начале каждой игры, вы убедитесь , что все данные , которые так упорствуют из предыдущей сессии не ошибочно обрабатывается как данные из текущей сессии.
Вы можете увидеть PlayerPrefs
в действии, ниже. Обратите внимание, что когда я нажимаю «Сохранить данные», я напрямую вызываю Save
метод, а когда я нажимаю «Загрузить данные», я напрямую вызываю Load
метод. Ваша собственная реализация, вероятно, будет отличаться, но она демонстрирует основы.
В заключение, я должен отметить, что вы можете расширить базовые возможности PlayerPrefs
для хранения более полезных типов. JPTheK9 дает хороший ответ на аналогичный вопрос , в котором они предоставляют сценарий для сериализации массивов в строковую форму, которая будет храниться в PlayerPrefs
файле. Они также указывают нам на вики-сайт Unify Community , где пользователь загрузил более обширный PlayerPrefsX
скрипт для поддержки большего разнообразия типов, таких как векторы и массивы.