Ідеальний спосіб зберігання змінних між сценами - через клас одиночного менеджера. Створивши клас для зберігання стійких даних та встановивши його для цього DoNotDestroyOnLoad()
, ви можете переконатися, що він є негайно доступним та зберігається між сценами.
Ще одним варіантом є використання PlayerPrefs
класу. PlayerPrefs
призначений для того, щоб ви могли зберігати дані між ігровими сесіями , але він все одно буде служити засобом для збереження даних між сценами .
Використання однокласного класу та DoNotDestroyOnLoad()
Наступний скрипт створює стійкий однокласний клас. Клас синглтон - це клас, який призначений для запуску лише одного екземпляра одночасно. Забезпечивши таку функціональність, ми можемо сміливо створити статичну само посилання, щоб отримати доступ до класу з будь-якого місця. Це означає, що ви можете безпосередньо отримувати доступ до класу 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 Wiki , де користувач завантажив більш розширений PlayerPrefsX
сценарій, щоб забезпечити підтримку більшої кількості типів, таких як вектори та масиви.