Сохранение игры unity 3d
Прошу помочь, сейчас занимаюсь над сохранением игры и возникла проблема. Если вкратце, у меня аркада под андроид, в каждом уровне которой можно заработать типо коинов, а перед началом каждого уровня у меня есть панель с общим количеством этих самых коинов. Вот сбилдил я игру на андроид и получилось, что каждый раз когда я выхожу из игра и захожу заново, эти коины не сохраняются и сбрасываются до нуля. То же самое и с уровнями, у меня уровни random.range определяются , и каждый раз как я перезахожу сбрасывается на первый уровень, но это не так критично, как с монетками.(Я знаю про playerprefs но не понимаю как его использовать в моем случае) Заранее спасибо
Отслеживать
задан 17 июл 2021 в 11:54
Миша Тощенко Миша Тощенко
3 1 1 бронзовый знак
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Для этого в Unity есть инструмент PlayerPrefs. Для записи( обновляй префс по ключу «coins» каждый раз, когда игрок берёт монетку)
PlayerPrefs.SetInt("coins",_coins); PlayerPrefs.Save();
Метод GetInt используй для чтения. В твоём случае верно будет сделать так:
_coinsCounter.text = PlayerPrefs.GetInt("coins");
Отслеживать
ответ дан 17 июл 2021 в 13:28
singletonsEnjoyer singletonsEnjoyer
139 5 5 бронзовых знаков
Лучше всего использовать что то надёжнее чем PlayerPrefs так как он сохраняет на устройстве не защищенные данные которые пользователь сможет изменить без особых проблем, грубо говоря взломать, но для первого опыта можно взять его.
Для создания PlayerPrefs необходимо понимать термин ключ (key) — это string наименование, которое хранить в себе на устройстве переданное значение определенного типа, PlayerPrefs позволяет сохранять значения трёх типов: Int , String , Float .
Его основные методы:
PlayerPrefs.SetInt(string keyName, int value); // Передает значение value в ключ keyName
PlayerPrefs.GetInt(string keyName); // Возвращает значение из ключа keyName
PlayerPrefs.SetFloat(string keyName, float value); // Передает значение value в ключ keyName
PlayerPrefs.GetFloat(string keyName); // Возвращает значение из ключа keyName
PlayerPrefs.SetString(string keyName, string value); // Передает значение value в ключ keyName
PlayerPrefs.GetString(string keyName); // Возвращает значение из ключа keyName
PlayerPrefs.DeleteKey(string keyName); // Удаляет полностью ключ.
PlayerPrefs.DeleteAll(); // Удаляет все ключи
PlayerPrefs.HasKey(string keyName); // Возвращает true если ключ существует, false если ключа нет
PlayerPrefs.Save(); // Сохраняет изменения на устройство (По умолчанию это делается при выходе из приложения, в случаях сбоя и экстренного выхода из приложения данные не будут сохранены). Имейте в виду что вызов данного метода вызывает тормоза, и следует вызывать его в не игровом процессе
Пример сохранения монеток:
[SerializeField] private Text _coinsText; // Ссылка на обьект с текстом монет private const int DEFAULT_VALUE = 0; // константа с значением по умолчанию, когда ключ ещё не создан (первый запуск игры) private const string COINS_AMOUNT_PREFS = "coins_amount"; // константа с ключём (создана для исключения ошибок при наборе ключа в ручную через "кавычки") if(PlayerPrefs.HasKey(COINS_AMOUNT_PREFS )) // Проверка если ключ имеется < _coinsText.text = PlayerPrefs.GetInt(COINS_AMOUNT_PREFS).ToString(); // Назначаем тексту значение >else < PlayerPrefs.SetInt(COINS_AMOUNT_PREFS , DEFAULT_VALUE); // Создаем ключ с базовым значением _coinsText.text = PlayerPrefs.GetInt(COINS_AMOUNT_PREFS).ToString(); // Назначаем тексту значение с ключа который только что создали >
Каким способом сохранять игровые данные для Android/IOS?
Игра на Unity и представляет из себя вождение авто в открытом мире, также в игре можно заниматься перевозкой пассажиров, тем самым зарабатывая деньги, есть тюнинг для авто. И вот нужно сохранять эти данные о купленных авто, о купленных улучшениях. Конечно же, сама логика покупок кое-как реализована, просто нужно сохранять эти покупки, кол-во монет и т. д. Я уже ознакомился с двумя способами сохранения, первый способ, через использование класса «PlayerPrefs», но этот класс не сохраняет данные типа «bool», которые имеют в проекте первостепенную роль, этот вариант отпадает (конечно, если вы не предложите обход использования «bool», заменив его на «int» и назначая таким данным «0» или «1», а надёжен ли такой способ? А может быть можно модернизировать этот класс так, чтобы он также работал с «bool»?), второй вариант «сериализация», но автор урока подчеркнул, что сериализация может быть проблемной с OS «Android» и «IOS». Как быть тогда? Мне желательно не громоздкий способ, но чтобы сохранял всё вышеперечисленное.
- Вопрос задан более трёх лет назад
- 1657 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 2
GavriKos @GavriKos Куратор тега Unity
Берете все данные, которые вам нужно сохранить, загоняете в json/xml, и сохраняете в PlayerPrefs как строку.
Для оптимизации можете подробить на логические элементы.
Ответ написан более трёх лет назад
Комментировать
Нравится 3 Комментировать
shai_hulud @shai_hulud
Создайте свою структуру классов/списков итд для сохранения мира из обычных C# классов с публичными свойствами и и публичными пустыми конструкторами. Сохраните все свои данные в эту структуру и сериализуйте в файл. Для сериализации выберите любой из предоставленных ассетов для бинарных форматов и скормите ему ваши классы/списки:
https://assetstore.unity.com/search?q=bson или
https://assetstore.unity.com/search?q=messagepack
Хотя на самом деле JSON местами компактнее BSON, и его тоже можно использовать. JSON.NET неплох. Если нужна мультиплатформа то вот JSON & MessagePack работает везде.
Для того что бы выбрать папку для сохранения можно воспользоваться следующим кодом:
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN || UNITY_WP8 var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); #else var appData = Environment.GetFolderPath(Environment.SpecialFolder.Personal); #endif
Для создания файла в этой папке можно использовать следующий код:
using(var writer = File.CreateText(Path.Combine(appData , "mysave.json"))
Для непосредственного сохранения в файл с Json.NET:
var serializer = new JsonSerializer(); serializer.Serialize(writer, myData)
Ну, и совет напоследок, не сохранять каждый раз в один и тот же файл, а делать это последовательно в разные файлы, на случай "битого" сохранения.
Как сохранить игру в unity для андроид
Главная » Как сохранять и загружать данные игры в Unity
Как сохранять и загружать данные игры в Unity
Узнайте, как сохранять и загружать игру в Unity с помощью PlayerPrefs, Serialization и JSON. Дополните свой пользовательский опыт знаниями о том, как сохранять и загружать данные.
Игры становятся все длиннее и больше, некоторые из них содержат более 100 часов контента. Невозможно ожидать, что игроки смогут завершить все, что может предложить игра, всего за один присест. Вот почему позволить игроку сохранить свою игру — одна из самых важных функций, которую должна иметь ваша игра, даже если это просто отслеживание игрового счета.
Но как создать файл сохранения и что в нем должно быть? Вам также нужно использовать файл сохранения, чтобы отслеживать настройки игрока? Как насчет отправки сохранений в интернет, чтобы их можно было позже загрузить на другое устройство?
В этом уроке вы узнаете:
- Что такое сериализация и десериализация.
- Что такое PlayerPrefs и как его использовать для сохранения настроек игрока.
- Как создать файл сохранения игры и сохранить его на диск.
- Как загрузить файл сохранения игры.
- Что такое JSON и как его использовать.
Предполагается, что у вас есть некоторые базовые практические знания о том, как работает Unity (например, возможность создавать и открывать скрипты), но кроме этого все было подготовлено, так чтобы этому руководству было очень легко следовать. Даже если вы новичок в C#, у вас не должно возникнуть проблем, за исключением нескольких концепций, которые могут потребовать дальнейшего изучения.
Примечание. Если вы новичок в Unity или хотите получить больше навыков в Unity, вам следует ознакомиться с другими уроками по Unity, где вы можете узнать о множестве тем Unity от C# до того, как работает пользовательский интерфейс.
Приступая к работе
Скачайте стартовый проект вверху страницы. Вы будете реализовывать код для сохранения и загрузки игры, а также логику сохранения настроек игроков.
Важные концепции сохранения
Есть четыре ключевых концепций сохранения в Unity:
PlayerPrefs: это специальная система кэширования для отслеживания простых настроек игрока между игровыми сессиями. Многие начинающие программисты ошибаются, полагая, что они могут использовать данную технологию как систему сохранения игры, но это плохая практика. Это следует использовать только для отслеживания простых вещей, таких как графика, настройки звука, данные для входа в систему или другие основные данные, связанные с пользователем.
Сериализация: это волшебство, благодаря которому Unity работает. Сериализация — это преобразование объекта в поток байтов. Определение может показаться расплывчатым, но взгляните на этот рисунок:
Что такое «объект»? В этом случае «объектом» является любой скрипт или файл в Unity. Фактически, всякий раз, когда вы создаете скрипт MonoBehaviour, Unity использует сериализацию и десериализацию для преобразования этого файла в код C++, а затем обратно в код C#, который вы видите в окне инспектора. Если вы когда-либо добавляли [SerializeField] , чтобы что-то отображалось в инспекторе, теперь вы имеете представление о том, что происходит.
Примечание. Если вы Java-разработчик или веб-разработчик, возможно, вы знакомы с концепцией, известной как маршаллинг. Сериализация и маршаллинг в общих чертах синонимичны, но если вам интересно, какова будет строгая разница, сериализация — это преобразование объекта из одной формы в другую (например, объекта в байты), тогда как маршаллинг — это получение параметров из одного места в другое.
Десериализация: это именно то, на что похоже. Это противоположность сериализации, а именно преобразование потока байтов в объект.
JSON: это обозначает нотацию объектов JavaScript, которая является удобным форматом для отправки и получения данных, не зависящих от языка. Например, у вас может быть веб-сервер, работающий на Java или PHP. Вы не можете просто отправить объект C#, но вы можете отправить JSON-представление этого объекта и позволить серверу воссоздать его локализованную версию. Вы узнаете больше об этом формате в последнем разделе урока, а пока что просто знайте, что это просто способ форматирования данных, чтобы сделать их удобочитаемыми для разных платформ (например, XML). При преобразовании в JSON и обратно используются термины сериализация JSON и десериализация JSON соответственно.
Player Prefs
Этот проект настроен так, что все, на чем вы будете сосредоточены, — это на логике сохранения и загрузки игр. Однако, если вам интересно, как все это работает, не бойтесь открыть все скрипты и посмотреть, что происходит, и не стесняйтесь задавать вопросы, если вам нужна помощь.
Откройте проект, затем откройте сцену с именем Game и нажмите на кнопку воспроизведения.
Чтобы начать игру, нажмите на кнопку New Game. Чтобы воспроизвести игру, вы просто перемещаете мышь, и пистолет будет следовать за вашим движением. Нажмите левой кнопкой мыши, чтобы выстрелить и поразить цели (которые переворачиваются вверх и вниз через различные промежутки времени), чтобы получить игровой счет. Попробуйте и посмотрите, какой счет вы сможете набрать за тридцать секунд. Чтобы вызвать меню в любое время, нажмите кнопку esc на клавиатуре.
Какой бы забавной ни была эта игра, без музыки она могла бы быть немного суховата. Вы могли заметить, что есть переключатель музыки, но он был выключен. Нажмите на play, чтобы начать новую игру, но на этот раз установите переключатель Music на включенное положение, и при запуске игры вы услышите музыку. Убедитесь, что колонки компьютера включены!
Изменить настройки музыки было просто, но нажмите на кнопку воспроизведения еще раз, и вы заметите проблему: музыка больше не проверяется. Несмотря на то, что вы меняли настройки музыки ранее, это изменение не отслеживалось. Это то, в чем PlayerPrefs преуспевает.
Создайте новый скрипт с именем PlayerSettings в папке Scripts. Поскольку вы будете использовать некоторые элементы пользовательского интерфейса, добавьте следующую строку вверху файла с другими пространствами имен:
using UnityEngine.UI;
Затем добавьте следующие переменные:
[SerializeField] private Toggle toggle; [SerializeField] private AudioSource myAudio;
Они будут отслеживать объекты Toggle и AudioSource.
Затем добавьте следующую функцию:
public void Awake () < // 1 if (!PlayerPrefs.HasKey("music")) < PlayerPrefs.SetInt("music", 1); toggle.isOn = true; myAudio.enabled = true; PlayerPrefs.Save (); >// 2 else < if (PlayerPrefs.GetInt ("music") == 0) < myAudio.enabled = false; toggle.isOn = false; >else < myAudio.enabled = true; toggle.isOn = true; >> >
После настройки скрипт будет:
- Проверять, есть ли в PlayerPrefs кэшированная настройка для ключа «music». Если там нет значения, он создает пару ключ-значение для музыкального ключа со значением 1. Он также включает переключатель и включает AudioSource. Это будет запущено при первом запуске игры. Значение 1 используется, потому что вы не можете сохранить логическое значение (но вы можете использовать 0 как false и 1 как true).
- Проверять ключ «music», сохраненный в PlayerPrefs. Если значение установлено на 1, в проигрывателе была музыка, поэтому он включает музыку и устанавливает переключатель в положение «включено». В противном случае он отключает музыку и переключатель.
Теперь сохраните изменения в скрипте и вернитесь в Unity.
Добавьте скрипт PlayerSettings в игровой объект Game. Затем разверните игровой объект UI, а затем игровой объект Menu, чтобы открыть его дочерние элементы. Затем перетащите игровой объект Music в поле Toggle скрипта PlayerSettings. Затем выберите игровой объект Game и перетащите AudioSource в поле MyAudio.
Музыка настроена на работу при запуске игры (поскольку в функции Awake есть код), но вам все равно нужно добавить код, если игрок изменяет настройки во время игры. Откройте скрипт PlayerSettings и добавьте следующую функцию:
public void ToggleMusic() < if (toggle.isOn) < PlayerPrefs.SetInt ("music", 1); myAudio.enabled = true; >else < PlayerPrefs.SetInt ("music", 0); myAudio.enabled = false; >PlayerPrefs.Save (); >
Это почти то же самое, что и код, который вы написали ранее, за исключением одного важного отличия. Он проверяет состояние переключателя музыки, а затем соответствующим образом обновляет сохраненную настройку. Чтобы этот метод был вызван и, следовательно, чтобы он мог выполнять свою работу, вам необходимо установить метод обратного вызова для игрового объекта Toggle. Выберите игровой объект Music и перетащите игровой объект Game на поле объекта в разделе OnValueChanged:
Выберите раскрывающийся список, в котором сейчас указано No Function, и выберите PlayerSettings -> ToggleMusic (). Когда кнопка переключения в меню нажата, она вызывает функцию ToggleMusic.
Теперь у вас есть все необходимое, чтобы отслеживать настройку музыки. Нажмите Play и попробуйте, включив или выключив переключатель музыки, затем завершите сеанс воспроизведения и начните новый сеанс воспроизведения.
Теперь настройки музыки сохранены правильно! Отличная работа, но возможности сериализации только начинаются.
Сохранение игры
Использовать PlayerPrefs было довольно просто, не так ли? С его помощью вы сможете легко сохранить в нем другие настройки, такие как графические настройки плеера или информацию для входа (например, токены Facebook или Twitter), а также любые другие настройки конфигурации, которые имеет смысл отслеживать для игрока. Однако PlayerPrefs не предназначен для отслеживания сохраненных игр. Для этого вы захотите использовать сериализацию.
Первым шагом к созданию файла сохранения игры является создание класса файла сохранения. Создайте скрипт с именем Save и удалите наследование MonoBehaviour . Удалите также стандартные методы Start () и Update () .
Затем добавьте следующие переменные:
public List livingTargetPositions = new List(); public List livingTargetsTypes = new List(); public int hits = 0; public int shots = 0;
Чтобы сохранить игру, вам нужно будет отслеживать, где находятся существующие роботы и к какому типу они относятся. Два списка выполняют эту задачу. Для количества попаданий и выстрелов вы просто сохраните их как целые числа.
Вам нужно добавить еще один очень важный фрагмент кода. Над объявлением класса добавьте следующую строку:
[System.Serializable]
Такая запись называется атрибутом, и это метаданные для кода, которые сообщают Unity, что класс можно сериализовать, и означают, что вы можете превратить объект в поток байтов и сохранить в файл на диске.
Примечание. Атрибуты имеют широкий спектр применения и позволяют прикреплять данные к классу, методу или переменной (эти данные известны как метаданные). Вы даже можете определить свои собственные атрибуты для использования в коде. Сериализация использует атрибуты [SerializeField] и [System.Serializable] , чтобы знать, что писать при сериализации объекта. Другие варианты использования атрибутов включают настройки для модульных тестов и внедрения зависимостей, которые выходят за рамки этого урока, но их стоит изучить.
Весь скрипт сохранения save должен выглядеть так:
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Save < public ListlivingTargetPositions = new List(); public List livingTargetsTypes = new List(); public int hits = 0; public int shots = 0; >
Затем откройте скрипт Game и добавьте следующий метод:
private Save CreateSaveGameObject() < Save save = new Save(); int i = 0; foreach (GameObject targetGameObject in targets) < Target target = targetGameObject.GetComponent(); if (target.activeRobot != null) < save.livingTargetPositions.Add(target.position); save.livingTargetsTypes.Add((int)target.activeRobot.GetComponent().type); i++; > > save.hits = hits; save.shots = shots; return save; >
Этот код создает экземпляр класса Save, который вы создали ранее, а затем устанавливает значения из существующих роботов. Он также сохраняет выстрелы и попадания игроков.
Кнопка Save подключена к методу SaveGame в скрипте Game, но кода в SaveGame пока нет. Замените функцию SaveGame следующим кодом:
public void SaveGame() < // 1 Save save = CreateSaveGameObject(); // 2 BinaryFormatter bf = new BinaryFormatter(); FileStream file = File.Create(Application.persistentDataPath + "/gamesave.save"); bf.Serialize(file, save); file.Close(); // 3 hits = 0; shots = 0; shotsText.text = "Shots: " + shots; hitsText.text = "Hits: " + hits; ClearRobots(); ClearBullets(); Debug.Log("Game Saved"); >
Рассматриваем комментарий за комментарием:
- Создать экземпляр Save со всеми данными текущего сеанса, сохраненными в нем.
- Создать BinaryFormatter и FileStream, передав путь для сохраняемого экземпляра Save. Он сериализует данные (в байты), записывает их на диск и закрывает FileStream. Теперь на вашем компьютере будет файл с именем gamesave.save. Файл .save использовался только в качестве примера, и вы могли использовать любое расширение для имени сохранения файла.
- Это просто сбрасывает игру, так что после сохранения игроком все находится в состоянии по умолчанию.
Чтобы сохранить игру, нажмите Escape в любой момент во время игры и нажмите кнопку Save. Вы должны заметить, что все сбрасывается, и в выводе консоли отображается примечание о том, что игра была сохранена.
LoadGame в скрипте Game связана с кнопкой Load. Откройте скрипт игры и найдите функцию LoadGame . Замените его следующим:
public void LoadGame() < // 1 if (File.Exists(Application.persistentDataPath + "/gamesave.save")) < ClearBullets(); ClearRobots(); RefreshRobots(); // 2 BinaryFormatter bf = new BinaryFormatter(); FileStream file = File.Open(Application.persistentDataPath + "/gamesave.save", FileMode.Open); Save save = (Save)bf.Deserialize(file); file.Close(); // 3 for (int i = 0; i < save.livingTargetPositions.Count; i++) < int position = save.livingTargetPositions[i]; Target target = targets[position].GetComponent(); target.ActivateRobot((RobotTypes)save.livingTargetsTypes[i]); target.GetComponent().ResetDeathTimer(); > // 4 shotsText.text = "Shots: " + save.shots; hitsText.text = "Hits: " + save.hits; shots = save.shots; hits = save.hits; Debug.Log("Game Loaded"); Unpause(); > else < Debug.Log("No game saved!"); >>
Рассмотрим код детально:
- Проверить, существует ли файл сохранения. Если это так, он очищает роботов и счет. В противном случае на консоль выводится сообщение об отсутствии сохраненной игры.
- Подобно тому, что вы делали при сохранении игры, вы снова создаете BinaryFormatter, только на этот раз вы предоставляете ему поток байтов для чтения вместо записи. Таким образом, вы просто передаете ему путь к файлу сохранения. Он создает объект Save и закрывает FileStream.
- Несмотря на то, что у вас есть информация о сохранении, вам все равно нужно преобразовать ее в состояние игры. Этот код просматривает сохраненные позиции роботов (для живых роботов) и добавляет робота в эту позицию. Он также устанавливает для него правильный тип. Для простоты таймеры сброшены, но вы можете удалить это, если хотите. Это предотвращает немедленное исчезновение роботов и дает игроку несколько секунд, чтобы сориентироваться в мире. Кроме того, для простоты анимация движения робота вверх настроена на завершение, поэтому роботы, частично движущиеся вверх при сохранении, будут отображаться полностью вверх при загрузке игры.
- Это обновляет пользовательский интерфейс, чтобы установить правильные попадания и выстрелы, и устанавливает локальные переменные, чтобы, когда игрок стреляет или попадает в цель, он продолжает отсчитывать значение, которое было ранее. Если вы не сделали этого шага, в следующий раз, когда игрок выстрелит или поразит цель, отображаемые значения будут установлены на 1.
Нажмите Play, поиграйте в игру и сохраните. Нажмите кнопку Load, и вы увидите, что враги загружаются в том виде, в котором они были настроены раньше, когда вы сохранили игру. Он также правильно устанавливает ваш счет и нанесенные вами выстрелы.
Сохранение данных с помощью JSON
Есть еще один прием, который вы можете использовать, когда хотите сохранить данные, - это JSON. Вы можете создать локальное JSON-представление сохранения игры, отправить его на сервер, затем получить этот JSON (в виде строки) на другое устройство и преобразовать его из строки обратно в JSON. В этом уроке не рассматривается отправка / получение из интернета, но очень полезно знать, как использовать JSON - и это невероятно просто.
Формат JSON может немного отличаться от формата кода C#, но это довольно просто. Вот простой пример JSON:
Внешние скобки представляют родительский объект, который является JSON. Если вы знакомы со структурой данных Dictionary , то JSON похож. Файл JSON представляет собой сопоставление пар ключей и значений. Итак, в приведенном выше примере есть 3 пары ключ-значение. В JSON ключи всегда являются строками, но значения могут быть объектами (т.е. дочерними объектами JSON), массивами, числами или строками. Значение, установленное для ключа «message» - «hi», значение ключа «age» - число 22, а значение ключа «items» представляет собой массив с двумя строками в нем.
Сам объект JSON представлен типом String. Передав эти данные в виде строки, любой язык может легко воссоздать объект JSON из строки в качестве аргумента конструктора. Очень удобно и очень просто.
У каждого языка есть свой способ создания объекта из этого формата. Начиная с Unity 5.3 существует собственный метод для создания объекта JSON из строки JSON. Вы создадите JSON-представление рекорда игрока, а затем распечатаете его на консоли. Но вы расширяете эту логику, отправляя JSON на сервер.
В скрипте Game есть метод с именем SaveAsJSON, который подключен к кнопке SaveAsJSON. Замените SaveAsJSON следующим кодом:
public void SaveAsJSON()
Это создает экземпляр Save, как и раньше. Затем он создает строку JSON, используя метод ToJSON в классе JsonUtility. Затем он выводит результат на консоль.
Начните игру, поразите несколько целей, затем нажмите Escape, чтобы открыть меню. Нажмите кнопку SaveAsJSON, и вы увидите созданную вами строку JSON:
Если вы хотите преобразовать этот JSON в экземпляр Save , вы должны просто использовать:
Save save = JsonUtility.FromJson(json);
Именно так вы поступили бы, если бы захотели загрузить файл сохранения из интернета, а затем загрузить его в свою игру. Но настройка веб-сервера - это совсем другой процесс! А пока похлопайте себя по плечу, потому что вы только что выучили несколько приемов, которые . избавят вас от неприятностей в следующей игре!
Куда двигаться дальше?
Вы можете скачать итоговые файлы проекта вверху страницы.
Теперь вы получили мощный инструмент для создания отличных игр, позволяющий игрокам сохранять и загружать свои игры с помощью магии сериализации. Вы также узнали, что такое JSON и как его можно использовать для сохранения в облаке. Вы также узнали, для чего используется PlayerPrefs (настройки!) И для чего он не используется (сохранение игры).
Вы всегда можете оставить здесь комментарий, если у вас есть какие-либо вопросы по этому руководству, присоединяйтесь к обсуждению ниже!
Простой способ: PlayerPrefs
Для начала можно закомментировать или удалить методы Start и Update , так как они не потребуются для демонстрации сохранения данных. Затем нам понадобятся несколько переменных.
Загрузка
Загрузка сохраненных данных – это, по сути, сохранение наоборот. Необходимо взять значения, хранящиеся в PlayerPrefs и записать их в переменные.
Хорошей практикой является предварительная проверка наличия нужных ключей. Для этого предназначен метод HasKey . Достаточно проверить хотя бы один ключ из установленных в методе SaveGame , чтобы понимать, есть ли у пользователя сохраненные данные.
Если данных нет, выведем в консоль сообщение об ошибке.
Теперь запустите игру и начните взаимодействовать с GUI-элементами. Изменяйте переменные, нажимая на кнопки и заполняя текстовое поле. Когда будете готовы, сохраните данные кнопкой Save Your Game . После этого остановите и перезапустите игру и нажмите на кнопку Load Your Game . Если вы всё сделали правильно, значения переменных немедленно изменятся на те, что вы сохранили в предыдущем запуске.
Чтобы очистить PlayerPrefs , кликните Reset Save Data .
Недостатки
Этот способ кажется простым и эффективным. Почему бы всегда не использовать PlayerPrefs для сохранения пользовательских данных?
Из-за его невысокой безопасности. Вы точно не захотите сохранять таким способом данные, в которые не должен вмешиваться игрок: например, количество доступной игроку игровой валюты, или статистика.
Из названия понятно, что PlayerPrefs предназначен для хранения пользовательских предпочтений и других неигровых данных. Например, этот метод идеально подходит для записи настроек интерфейса: цветовой темы, размера элементов и т. п.
Другая проблема – в недостаточной гибкости. В PlayerPrefs вы можете сохранять только числа и строки, поэтому он не подходит для данных, имеющих сложную структуру.
К счастью, у нас есть еще один способ, более гибкий и безопасный.
Сложный способ: Сериализация
Для демонстрации сложного способа сохранения данных в Unity откроем скрипт SaveSerial .
Снова определим переменные и создадим интерфейс для управления ими. Метод OnGUI похож на тот, что мы только что писали:
Обратите внимание, три переменные в классе SaveData соответствуют переменным из класса SaveSerial . Для сохранения мы будем передавать значения из SaveSerial в SaveData , а затем сериализовать последний.
Добавим в класс SaveSerial метод SaveGame :
После запуска вы увидите тот же самый интерфейс, что и раньше. Попробуйте изменить переменные и сохранить игру.
В этот раз файл будет сохранен по "постоянному пути данных" игры. В Windows это C:\Users\username\AppData\LocalLow\project name , в Mac – ~/Library/Application Support/companyname/productname согласно документации.
Перезапустите игру и загрузите данные, нажав на кнопку Load Your Game . Значения переменных должны измениться на те, что вы сохранили ранее.
Также вы можете удалить все сохраненные данные кнопкой Reset Save Data .
Заключение
Сохранение данных – важная часть большинства игр, за исключением лишь некоторых специфических исключений (например, игры с очень короткими игровыми сессиями или механикой перманентной смерти, в которой после каждого проигрыша вся игра сбрасывается к началу).
Помните о том, что PlayerPrefs – это простой способ сохранить настройки и предпочтения пользователя, но его не следует использовать для записи важных игровых данных.
Сериализация и запись в файл – более сложный путь, но он дает вам бóльшую гибкость и безопасность.
Какие именно данные сохранять и каким способом – зависит от особенностей проекта.
Больше полезной информации вы найдете на наших телеграм-каналах «Библиотека программиста» и «Книги для программистов».