Сохранение прогресса unity android

Сохранение прогресса unity android

Fox_game 26 сен 2017, 13:07

Re: Сохранения для игр на телефон.

Alex_Hell 27 сен 2017, 01:18

Re: Сохранения для игр на телефон.

Fox_game 27 сен 2017, 11:19

Alex_Hell писал(а): 1й незащищенный — на мобилах пашет — крякабельный легко
https://docs.unity3d.com/ru/530/ScriptR . Prefs.html

Re: Сохранения для игр на телефон.

Pollux 27 сен 2017, 14:49

Re: Сохранения для игр на телефон.

Fox_game 28 сен 2017, 09:59

именно с этими палочками (\)? или с этими (/)
И где использовать Application.persistentDataPath?

я заменил на это:

Re: Сохранения для игр на телефон.

alt3d 28 сен 2017, 10:20

Вместо Application.dataPath используй Application.persistentDataPath
Юнити генерирует эту папку на телефоне по имени твоего приложения и изменяет права доступа так что ты можешь туда писать что хочешь.

И не надо городить огород с «sdcard0/Android/data/saves/save.zorya»
сразу пиши Application.persistentDataPath + «save.zorya»

Re: Сохранения для игр на телефон.

Fox_game 28 сен 2017, 18:56

alt3d писал(а): Вместо Application.dataPath используй Application.persistentDataPath
Юнити генерирует эту папку на телефоне по имени твоего приложения и изменяет права доступа так что ты можешь туда писать что хочешь.

И не надо городить огород с «sdcard0/Android/data/saves/save.zorya»
сразу пиши «Application.persistentDataPath/save.zorya»

Re: Сохранения для игр на телефон.

Tolking 28 сен 2017, 19:40

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB

Источник

Как выполнять сохранение и загрузку игры в Unity

Авторизуйтесь

Как выполнять сохранение и загрузку игры в Unity

Совсем недавно мы опубликовали серию уроков (1 часть, 2 часть, 3 часть, 4 часть) по созданию простой игры, используя очень распространенный игровой движок — Unity. В этой статье мы покажем, как организовать систему управления сохраненными играми в Unity. Мы будем писать меню как в Final Fantasy, где игроку предоставляется возможность создать новое уникальное сохранение или же продолжить уже существующее. Итак, к концу урока вы научитесь:

  • сохранять игру и загружать уже имеющуюся, используя сериализацию;
  • использовать статические переменные для сохранения данных при изменении сцены.

Подготовка к сериализации

Первое, что нам нужно сделать, это сериализовать наши данные, которые мы сохраним, а затем в нужное время восстановим. Для этого нам потребуется создать скрипт (в качестве языка программирования будем использовать C#). Давайте назовем его SaveLoad . Этот сценарий будет обрабатывать все, что связано с сохранением и восстановлением данных.

Мы будем ссылаться на этот сценарий из других скриптов, а потому сделаем класс статичным, добавив ключевое слово static между public и class . Также не забудем удалить два автоматически созданных метода, поскольку нам не потребуется крепить скрипт ни к какому игровому объекту.

Полученный сценарий должен выглядеть вот так:

Мы хотим добавить немного функциональных возможностей нашему скрипту, а потому давайте пропишем несколько директив:

Первая строка позволит нам использовать динамические списки. Вторая — даст нужный функционал операционной системы по сериализации данных. А последняя директива позволяет нам работать с потоками ввода и вывода. Иными словами, она используется для создания и чтения файлов.

Отлично, теперь мы готовы к сериализации данных!

Создание класса, с возможностью сериализации

Игры, похожие на Final Fantasy (то есть многие RPG), предлагают игроку выбрать класс персонажа. Например, рыцарь, разбойник или маг. Создайте новый скрипт, назовите его Game и объявите в нем переменные:

Обратите внимание на строчку [System.Serializable] , которая говорит движку, что этот скрипт может быть сериализован. Круто, не так ли? Как говорит официальная документация, Unity умеет сериализовать следующие типы данных:

  • Все базовые типы ( int , string , float , bool и т.д.).
  • Некоторые встроенные типы ( Vector2 , Vector3 , Vector4 , Quaternion , Matrix4x4 , Color , Rect и LayerMask ).
  • Все классы, унаследованные от UnityEngine.Object ( GameObject , Component , MonoBehavior , Texture2D и AnimationClip ).
  • Перечисляемый тип ( Enums ).
  • Массивы и списки типов данных, перечисленных выше.

Первая переменная, объявленная в нашем классе, — current — является статической ссылкой на экземпляр игры. Когда мы будем сохранять или загружать какие-либо данные, нам потребуется обратиться к «текущей» игре. При использовании статических переменных сделать это особенно просто, без вызова лишних методов. Очень удобно!

Обратите внимание на класс Character . Его еще у нас нет — давайте создадим новый скрипт с таким названием:

Ничего странного не заметили? Да, мы действительно создали новый класс, внутри которого есть ровно одна строковая переменная. Мы, конечно же, могли использовать в скрипте Game переменные типа string вместо экземпляров класса Character . Но целью нашей статьи является не то, как сделать лучше, а рассказать, как можно решить нашу проблему.

Теперь, когда наши классы настроены, перейдем обратно к скрипту SaveLoad и добавим возможность сохранения игры.

Сохранение игры

Что происходит по нажатию на кнопку «Загрузить игру»? Правильно — показывается список уже сохраненных игры, которые мы можем восстановить. Так давайте создадим список игр и назовем его savedGames:

А теперь напишем статическую функцию сохранения игры:

Разберемся с тем, что же выполняет эта функция. Сначала мы добавляем в ранее созданный список текущую игру. Так как в скрипте Game мы использовали статическую переменную current, то мы можем достаточно просто обратиться к ней: Game.current . После этого нам следует сериализовать список, для чего и создается экземпляр класса BinaryFormatter .

Далее при помощи класса FileStream мы создаем новый файл под названием savedGames.gd в специальной директории, в которой и должны храниться все игровые данные. Для названия файла сохранений будем использовать savedGames , а расширением будет gd (от словосочетания game data).

Читайте также:  Igo primo nextgen 4pda android

Примечание автора В качестве расширения файла вы можете использовать все, что угодно. Так, например, в играх The Elder Scrolls используется .esm .

Далее вызывается метод Serialize экземпляра класса BinaryFormatter , который и сохраняет в файл сериализованные данные. И на этом все — файл закрывается. Наша игра сохранена!

Загрузка игры

А здесь все довольно просто. Так как при сохранении игры мы создали файл и записали в него сериализованный список, то сейчас нам придется открыть его и десериализовать имеющиеся в нем данные:

Алгоритм предельно прост. Для начала мы проверяем, существует ли файл сохранений. Если существует, то мы создаем новый экземпляр класса BinaryFormatter , открываем файл savedGames.gd и записываем в список savedGames десериализованные данные, считанные из файла.

Обратите внимание на 5 строчку. Метод Deserialize вернет нам битовую последовательность и, присвоив списку savedGames то, что возвращает функция Deserialize , мы ни к чему хорошему не придем. И поэтому нам следует полученную битовую последовательность преобразовать (привести) к типу List .

Примечание автора Тип данных, к которому вы приводите десериализованные данные, может быть совершенно разным. Например: Player.lives = (int)bf.Deserialize(file); .

Вывод

Итак, теперь вы знаете, как реализовать систему сохранения и загрузки игровых данных. Наш скрипт готов, и в окончательном виде он выглядит вот так:

Таковы основы работы с игровыми данными в Unity. В файле проекта вы можете найти несколько других скриптов, которые демонстрируют, как я применяю написанные нами функции и как я отображаю данные при помощи Unity GUI.

Источник

Unity Android — гайды для начинающих

Поиск по этому блогу

  • Получить ссылку
  • Facebook
  • Twitter
  • Pinterest
  • Электронная почта
  • Другие приложения

Unity Android — как хранить данные на устройстве

  • Получить ссылку
  • Facebook
  • Twitter
  • Pinterest
  • Электронная почта
  • Другие приложения

Для сохранения пользовательских данных необходимо использовать встроенные методы движка Unity. В этой статье мы рассмотрим самый простой способ их хранения.

Начнем с того, что в Unity есть синглтон PlayerPrefs, который реализует методы сохранения трех типов данных — строки, числа типа float и числа типа int.

Все данные сохраняются под ключами, как в словаре или ассоциативном массиве. Давайте рассмотрим это на примере кода.

Данная команда записала в словарь пользовательских данных число с типом int под ключом «name». Но просто прописать данную команду недостаточно: нужно подствердить сохранение. Для этого просто вызываем:

Вот пример сохранения других типов:

Чтобы получить значение, воспользуемся get методами:

string data = PlayerPrefs.GetString(«nickname»);

int number = PlayerPrefs.GetInt(«name»);

float money = PlayerPrefs.GetFloat(«money»);

Если до этой игровой сессии данные были занесены, методы вернут сохраненные значения.

Источник

Каким способом сохранять игровые данные для Android/IOS?

Создайте свою структуру классов/списков итд для сохранения мира из обычных C# классов с публичными свойствами и и публичными пустыми конструкторами. Сохраните все свои данные в эту структуру и сериализуйте в файл. Для сериализации выберите любой из предоставленных ассетов для бинарных форматов и скормите ему ваши классы/списки:
https://assetstore.unity.com/search?q=bson или
https://assetstore.unity.com/search?q=messagepack
Хотя на самом деле JSON местами компактнее BSON, и его тоже можно использовать. JSON.NET неплох. Если нужна мультиплатформа то вот JSON & MessagePack работает везде.

Для того что бы выбрать папку для сохранения можно воспользоваться следующим кодом:

Для создания файла в этой папке можно использовать следующий код:

Для непосредственного сохранения в файл с Json.NET:

Ну, и совет напоследок, не сохранять каждый раз в один и тот же файл, а делать это последовательно в разные файлы, на случай «битого» сохранения.

+вроде бы с File.CreateText могут быть проблемы на тех же андроидах, и рекомендуется через потоковые функции типа WWW (или что там вместо него уже) работать.

Ну и все же — лучше использовать PlayerPrefs. Аргумент — сам движок гарантирует, что запись в это хранилище на конкретной платформе доступна и работает. А ваш код надо будет обновлять при выходе каких нибудь новых ОСей с замороченной безопасностью.

Тут соглашусь, лучше писать туда куда юнити решила, но доступ в папку Personal есть везде, даже на WebGL. Файловая система там симулируется.

В остальном, перфоманс и мусор в памяти у сохранения на файловую систему и PlayerPrefs не соразмерны. Не в пользу последнего. Плюс были случаи когда PlayerPrefs затирались при апдейтах. И ни по поводу «возможных проблем», соглашаясь на юнити, ты соглашаешься что всё что угодно завтра отвалится. Если сегодня работает, то шикарно, завтра если что костылями обложим.

Источник

Сохранение игры в Unity3D

Если вы пишете не казуалку под веб и не беспощадный суровый рогалик, без сохранения данных на диск не обойтись.
Как это делается в Unity? Вариантов тут достаточно — есть класс PlayerPrefs в библиотеке, можно сериализовать объекты в XML или бинарники, сохранить в *SQL*, можно, в конце-концов, разработать собственный парсер и формат сохранения.
Рассмотрим поподробнее с первые два варианта, и заодно попробуем сделать меню загрузки-сохранения со скриншотами.

Будем считать, что читающий дальше базовыми навыками обращения с этим движком владеет. Но при этом можно не подозревать о сущестовании в его библиотеке PlayerPrefs, GUI, и ещё в принципе не знать о сериализации. С этим всем и разберёмся.
А чтобы эта заметка не стала слишком уж увлекательной и полезной, ориентирована она самый неактуальный в мобильно/планшетно/онлайновый век вариант — сборку под винду (хотя, конечно, более общих моментов достаточно).

  • Кстати, пару недель назад на Хабре была статья, где автор упомянул, что Unity3D проходят в курсе компьютерной графики на кафедре информатики питерского матмеха. Занятный факт, немало говорящий о популярности движка.
    Хотя насколько это в целом хорошая идея — на мой взгляд, тема для дискуссии. Может быть, обсудить это было бы даже интереснее вопросов сериализации =)

Ещё небольшой дисклеймер — я не профи ни в одной из раскрываемых тем, так что если какие-то вещи можно сделать правильнее-проще-удобнее — исправления и дополнения очень приветствуются.

1. PlayerPrefs

Удобный встроенный класс. Работает с int, float и string. Довольно прозрачный, но мне всё равно встречались на форумах обороты в духе «не могу понять PlayerPrefs» или «надо бы как-нибудь разобраться с PlayerPrefs», так что посмотрим на него на простом примере.

1.1 Примитивное использование в рамках одной сцены: QuickSave & QuickLoad по хоткеям.

Быстрый пример использования. Допустим, у нас одна сцена и персонаж на ней. Скрипт SaveLoad.cs прикреплен к персонажу. Будем сохранять самое простейшее — его положение.

Читайте также:  Какие телефоны realme получат андроид 12

Конечно, тут применение PlayerPrefs довольно надумано — фактически против обычных переменных оно добавляет нам только возможность загрузки игру с места сохранения после выхода.

Зато весь основной интерфейс класса виден: для каждого из трех типов Get / Set по ключу, проверка вхождения по ключу, очистка. Нет смысла даже разбирать ScriptReference, всё очевидно по названиям функций: PlayerPrefs

Однако на одной всё же стоит остановиться подробнее, PlayerPrefs.Save. В описании говорится, что вообще дефолтно юнити пишет PlayerPrefs на диск только при закрытии приложения — в общем-то логично, учитывая, что класс ориентирован не на внутренний обмен данными, и на их сохранение между сеансами. Соответственно, Save() предполагается использовать только для периодических сохранений на случай крэша.

Возможно, в некоторых случаях это так и работает. Под Win PlayerPrefs пишутся в реестр, и, как можно легко убедиться, считываются и пишутся сразу.
Как-то так выглядит наш класс в реестре:

Ко всем ключам в конце добавлен их DJBX33X-хеш (Bernshtein hash with XOR).

UnityGraphicsQuality сохраняется всегда автоматически, и действительно при закрытии приложения. Это Quality level из Edit -> Project Settings Quality, оно же QualitySettings.SetQualityLevel .

Можно при запущенном приложении модифицировать сохранённое значение в реестре, потом затребовать его из программы — и мы увидим, что вернулся модифицированный вариант. Т.е. не стоит думать что во время работы программы PlayerPrefs — что-то вроде аналога глобальных переменных, а работа с диском не происходит.

2. Сериализация в XML

Говорим сериализация, подразумеваем бинарный код. Такое встречается, но на самом деле сериализовать можно в любой формат. По сути это перевод структуры данных или состояния объекта в хранимый/передаваемый формат. А десериализация, соответственно — восстановление объекта по сохраненным/полученным данным.

Вообще Mono умеет и бинарную сериализацию, и XML (System.Xml.Serialization), но есть один момент: большинство классов Unity не сериализуются напрямую. Невозможно просто взять и сериализовать GameObject, или класс, наследующий MonoBehavoir: придётся завести дополнительно внутренний сериализуемый класс, содержащий нужные данные, и работаеть, используя его. Но XmlSerializer хотя бы кушает автоматически Vector3, а BinarySerializer, afaik, даже этого не умеет.

2.1 Суть примера

Представьте, что вы пишете свой Portal, где герой проходит череду однотипных локаций — но на любую из них может впоследствии вернуться. Причём на каждую он мог оказать воздействие: какие-то ресурсы использовать, что-то сломать, что-то расшвырять. Хочется, эти изменения сохранять, но возвращение на локацию маловероятно и непрогнозируемо, и тащить за собой параметры всех комнат в оперативке нет особого смысла. Будем сериализовать локацию, покидая её — например, по триггеру на двери. А при загрузке локации генерировать либо дефолтную ситуацию, либо, если есть сохраненные данные, восстанавливать по ним.

2.2 Сериализуемые классы для данных

XmlSerializer умеет работать с классами, данные в которых состоят из других сериализуемых классов, простых типов, большинства элементов Collections[.Generic]. Обязательно наличие у класса пустого конструктора и public-доступ ко всем сериализуемым полям.
Некторые типы из библиотеки Юнити (вроде Vector3, содержащего всего три интовых поля) успешно проходят этот фейсконтроль, но большинство, особенно более сложных, его фейлят.

Допустим, в каждой комнате нам надо сохранять состояния некоторого произвольного набора GameObject’ов. Напрямую сделать этого мы не можем. Значит, нам потребуются дублирующие типы.

Создадим новый скрипт в Standard Assets:

В квадратных скобках идут атрибуты для управления XML-сериализацией. Тут они фактически влияют только на имена тегов в генерируемом *.xml, и строго говоря, необходимости в них нет. Но пусть будут, для наглядности 🙂 Если вам почему-то вдруг важно, как будет выглядеть xml-код, то возможности атрибутов, конечно шире.

Дальше там же добавим базовый класс для предметов из списка и сколько угодно наcледуемых от него. Хотя… для примера хватит и одного:

Итак, сериализуемые классы готовы. Сделаем теперь ещё класс для дополнительного упрощения сериализации созданного типа RoomState.

2.3 Непосредственно сериализация

Тоже в Standard Assets сделаем класс с парой статических методов, которыми будем в дальнейшем пользоваться:

Здесь XmlSerializer мы создаём через конструктор Constructor (Type, Type[])
FileStream открываем по адресу сохранения, передаваемого конкретной локацией.

Использование

Итак, все вспомогательные инструменты готовы, можно приступать к самой комнате. На объект комнаты вешаем:

Напоследок, сделаем вызов RoomGen.Dump(). Пусть, например, по триггерам на дверях, которые являются дочерними объектами относительно комнаты (объекта с компонентом RoomGen):

Вот и всё. Здесь опущено собственно взаимодействие с предметами и процесс изменения их состояния, но это несложно добавить. Для первоначального теста можно просто добавить в скрипт пару устанавливащих состояния функций по хоткеям, или ставить на паузу и двигать руками.

При первом запуску генерируется дефолтный вариант, при выходе изменения дампятся в файл, при возвращении последние состояние восстанавливается из файла, в том числе если приложение закрывалось. Works like a charm.

Один из существенных недостатков XML — игрок может легко изменить данные. И если в данном случае мало кого заинтересует расположение раскиданных стульев, то при сохранении более существенных для игрока данных сериализации в XML лучше избегать. Да и в реестре поменять значения не сложно. В таких случаях уже лучше использовать бинарную сериализацию или свой формат.

3. Save/Load через меню

Наверное, актуальнее было бы реализовать вариант с выбором/созданием пользователя и внутренними автоматическими сохранениями. Если вашей игре требуется серьёзное меню Save/Load, то вряд ли вы сейчас читаете эту статейку для профанов.

Но я жду не дождусь новогодних праздников, когда можно будет наконец увидеться с сестрой и за пару вечеров добить классическую American McGee’s Alice, так что сделаем Save/Load почти как там. Со скриншотами. Заодно будет повод покопаться в GUI, текстурах и других увлекательных вещах.

3.1 Главное меню

Чтобы сделать загрузку и сохранение через меню, нам, как ни странно, понадобится меню. Конечно, можно сделать его самостоятельно через объекты на сцене, можно заюзать готовые решения ироде NGUI , но мы пока воспользуемся GUI из штатной библиотеки.

    Scripting Reference
    Для начала пригодятся:
    OnGUI() — функция MonoBehaviour для отрисовки GUI и обработки связанных с ним событий. Нечто вроде Update(), но специально для GUI и вызываться может чаще, чем каждый фрейм.

функция кнопки. Рисует её в рамках заданного прямоугольника, реагирует на нажатие, возвращая true. Конструкторов больше, но нам хватит этих.

Читайте также:  Видеоплеер под андроид авто

Группировка элементов гуи, полезна в основном переопределением границ относительно которых вычисляется положение вложенных элементов (дефолтно это границы экрана, в данном случает — прямоугольник position).

  • Суть
    Сделаем отдельную стартовую сцену, а на ней пустой объект, к которому и прикрепим скрипт для нашего меню. Т.о. меню будет путешествовать сквозь сцены (при загрузке очередной сцены не пересоздаётся, а просто переносится в неё), хэндлить нужные события (вроде кнопки вызова меню), при вызове рисоваться поверх экрана игры.
  • по коду с комментариями всё должно быть ясно:
  • Главное меню до и после начала игры

    3.2 Рисуем меню загрузки / сохранения

    Функция drawSaveLoadMenu() у нас уже вызывается при menutype>0, но пока не написана. Исправим это упущение. Пока просто научимся рисовать наши меню и вызывать собственно функции загрузки/сохранения.

      Scripting Reference
      GUI.SelectionGrid — рисует сетку кнопок, но по сути это одновариантый селект. Всегда выбран один вариант, возвращает номер выбранного.

    Количество — исходя из размеров передаваемого массива. Вообще предназначен для использования как-то так:

  • Суть
    Кажется, это не совсем то, что нам требуется — нам-то нужно выбрать один раз и сразу отреагировать. Но SelectionGrid спокойно ест грязный хак — индекс вне пределов реального массива. Т.е. мы всегда будем передавать, допустим, -1 и тогда сможем отслеживать собственно событие клика.
  • Меню Load на SelectionGrid — внешне ничем не отличается от соответствующего Save

    Основное, что мне в этом решении не нравится, это что в меню загрузки не содержащие сохранений слоты остаются относительно активными — внешне отличаются только отсутствием текстуры, реагируют на наведение. Поэтому бонусом — сетка ручками, вместо неактивных слотов рисуем Box, для активных Button.
    Заодно добавим резиновости: количество слотов в строке задаётся, размер слотов подстраивается под экран. Правда, тут они уже квадратные, но встроить произвольное соотношение сторон будет несложно 🙂 Ну и заодно min/max width/height из GUILayout и прочая обработка напильником.

    Меню Load на Button и Box — теперь пустые слоты неактивны

    3.3 Текстуры, скриншоты

    Итак, с момента создания нашего объекта меню мы будем держать массив текстур. Памяти он занимает немного и нам гарантирован в ним мгновенный доступ. На самом деле, тут и альтернативы особой нет — не пихать же работу с диском в onGUI().

    Как мы уже видели, при создании нашего меню создаём и массив:

    Сохранять мы будем не только информацию сейвов, но и информацию о них, а точнее — какие именно слоты содержат сохранения. Как хранить — выбор каждого, можно по параметру 0/1 на каждый слот, можно строку из 0/1, но мы сделаем некрасиво 🙂 и возьмём битовый вектор в int. В какой момент и как он сохраняется, увидим позже, пока просто читаем.
    Добавим в Start():

    Ну и собственно главное в данном вопросе — как скрины сохранять? Напрашивается вариант Application.CaptureScreenshot , но тут сразу два подвоха. Во-первых, они сохраняются в полном размере, а поскольку в кончном итоге понадобятся нам только thumbnails, логичнее сразу сделать ресайз. Во-вторых, мы же держим массив текстур, придётся в него снова считывать с диска? Не очень-то здорово.

    Функцию взятия и записи скриншота вызывать будем позже, а пока заранее выделим в Coroutine:

    Неприятный нерешенный момент — текстура с текущей сессии и текстура, загруженная с диска, сильно различаются по качеству.
    Ниже слева две текущих, справа — две с диска, от предыдущих сессий:

    3.4 Собственно реализация сохранения загрузки

    Итак, вроде бы с шелухой разобрались. Научились минимально работе с GUI, сделали простое главное меню, меню Save/Load, научились работать со скриншотами.

    Как реализовать взаимодействие между объектами сцены, параметры которых мы будем сохранять и нашим меню?

    1. Если мы будем записывать только состояние такого же создаваемого с первой сцены и неразрушаемого далее объекта (например, игрок, его параметры и инвентарь) — можно сразу держать прямую ссылку.

    2. GameObject.Find и GameObject.FindWithTag тут использовать практически не стыдно — загрузка/сохранение — разовое событие. Можно искать напрямую, а поскольку сцены могут содержать разную информацию — то, как вариант, добавлять на каждую специальный объект с определенным тегом, к которому и будет прикручен скрипт сохранения/загрузки собственно данной сцены, тут уже можно держать прямые ссылки на требуемые объекты.

    А пока рассмотрим такой простой вариант. Сохранять будем только сцену и положение игрока. Игрок в каждой сцене пересоздаётся, но всегда вид от первого лица, и соответственно к игроку прикреплена камера.
    Через неё и будем получать доступ. В ниже представленной функции вся эта специфика — в двух строках помеченных //!, и её не сложно локально заменить, остальное привязано к уже написанному нами выше коду.

    Если делать скриншот заранее, то он во-первых, может не пригодится, а во-вторых, нужно ещё успеть. А так, с учётом заблокированности камеры в режиме меню, результат примерно тот же.

    С загрузкой ещё проще. Всё специфику мы снова полностью делегируем, причём даже не будем её напрямую вызывать. Просто загрузим нужный уровень, а дальше они как-нибудь сами 🙂

    Сделаем теперь поведение, который будем вешать на камеры:

    Надо заметить „дальше как-нибудь сами“ было определенной степенью лукавства: loadgame() меню и load() объекта определенно обменялись информацией, только вот через известное место — реестр. Сохранять туда откровенно временную переменную — ход не слишком красивый. Можно изменить на прямой вызов load(), а без изменения текущей общей структуры — держать переменную в меню, и в Start() загружаемого объекта добавить поиск объекта меню и получение нужной информации.

    Дальше. От созданного базового поведения мы можем унаследовать разные варианты для разных сцен и объектов. Например, вариант с сохранением поворота:

    Конечно, здесь данным уже пригодилась бы защита. Поскольку поскольку вся фактическая работа с PlayerPrefs тут выделена в отдельные функции save() / load(), заменить их содержательную часть будет не сложно. На что? Можно аналогично примеру из части 2 держать класс-рефлектор, и сериализовать его через BinarySerializer.
    Другой неплохой вариант — прикрутить, например, SQLite. Правда, по слухам, на js с ней работать удобнее, чем на шарпе, но и на последнем всё в конечном итоге заводится. Кто хочет попробовать, начать можно отсюда.

    Этот текст никогда бы не получился без:

    и хабра. Спасибо им.
    Надеюсь, всё это принесёт кому-нибудь пользу, и никому — вреда 🙂

    Источник

    Оцените статью