JSON Сохранения не работают на Android
Игра на Android
Сохраняется несколько параметров — На ПК работает, а на Android — Нет
Пробовал менять «streamingAssetsPath» на «persistentDataPath» и «dataPath» — Не помогло
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Всем привет. Есть такая проблема, имею игру на юнити и при написании одного из обновлений наткнулся.
RecyclerView сохранения в JSON
У меня есть recyclerview (в фрагменте) и фрагмент с детальной информацией к одному из элементов.
Как реализовать сохранения через Json
Всем доброго времени суток. Я делаю простецкую 2d игру для андроида в юнити (так сказать проба.
Законы сохранения энергии и импульса не работают?
Интересно, или укажите в чем ошибка или в чем дело пару книжек по теме перечитал там никаких.
XCC2Prime, хочешь можешь покопаться в теме, а если кратко то нужно в txt перевести и с путями поработать,
можешь такой скрипт юзнуть
DataSaver.saveData(название класса Saves, название файла «SaveData»);
и когда нужно в экземпляр класса можешь закинуть
Saves saveShop = DataSaver.loadData («SaveData»);
Darksiders 2 — не работают сохранения после переустановки ОС
Перебивал винду, предварительно сделал бэкап сэйвов. Сначала матюкалась на отсутствие msvcp100.dll.
Вот например страница: https://vk.com/market-73481857?section=album_43 После сохранения и .
Как организовать кнопку сохранения через JSON в Дельфи?
Подскажите , как организовать кнопку сохранения через JSON в делфи? Я сделал,но пока еще кнопка.
Куда сохранять файлы сохранения на Android?
Создают игру adventures. На уровне у меня есть сундуки и ящики. На каждом есть скрипт с массивом.
Android и JSON
Делал до этого просто получение данных от базы,посредством php-скрипта. Начал делать с.
Android JSON
Народ можете скинуть статеек или пару примеров написать как принимать. Настроил сервер на.
Источник
Не работает сохранение в Json файл
Доброго времени суток, я столкнулся с проблемой у меня есть кнопка по нажатию которой в список List<> добавляеться строка но в следующей строчке я сохраняю все изменения в файл json, и на етом моменте скорее всего какаята ошибка. В редакторе юнити всьо прекрасно работает но когда я компилирую игру на телефон то кнопка какбуто неработает. Я удалял строчку с сохранением и всьо работало, но естественно без сохранения.
Строчка с сохранением json.Save()
Вот скрипт кнопки:
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Добрый день уважаемые участники. Есть вопрос. Решил я сохранять настройки проги в json файл.
Сохранение в файл JSON
Необходимо сохранить данные в файл формата json. Имеется код: import psycopg2 import sqlite3.
Сохранение в json файл
Как сделать, чтобы данные c анкеты сохранялись в json файл? C#.
Сохранение List в Json файл
У меня есть класс(с сериалезацией), а нём список. Мне надо этот класс сохранить в формате Json, но.
Решение
под Windows
Application.dataPath Под Android.
Чтоб было проще, храни Json в Resources
и загружай через
И не будет мороки с Application.streamingAssetsPath
Добавлено через 3 минуты
Гдето из далеких глубин Unity гайдов
WWW для доступа к вашим файлам из StreamingAssets, так что используй Resources
Когда я питаюсь так сделать вибивает ошибку:
UnityException: Load is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour ‘JsonSaver’ on game object ‘GameManager’.
See «Script Serialization» page in the Unity Manual for further details.
UnityEngine.Resources.Load[T] (System.String path) (at :0)
Добавлено через 9 минут
Загрузка работает но при сохранении вибивает:
ArgumentException: Illegal characters in path.
System.IO.Path.GetFileName (System.String path) (at :0)
System.IO.StreamWriter.CreateFile (System.String path, System.Boolean append, System.Boolean checkHost) (at :0)
System.IO.StreamWriter..ctor (System.String path, System.Boolean append, System.Text.Encoding encoding, System.Int32 bufferSize, System.Boolean checkHost) (at :0)
Хотя путь нормальний
Добавлено через 12 минут
path ето получаеться не путь что ли? Немогу понять что именно не так.
а мне почему то кажется что туда просто не хочет писать
Добавлено через 56 секунд
товарищам иногда нужно читать доку
Я перепробовал все что було на етой странице форума и все что нашол и в итоге на пк в едиторе все работает а на телефоне нет.
Вот последнее что пробовал:
Короче я уже почти в одчайнии вернул все как било и заменил Application.dataPath на Application.persistentDataPath ниже код что заработал. Лучшим ответом я позначел тот ответ что мне больше остальних помог, Black спасибо большое что помогал мне все ето время.
мне этот способ нравится больше, в будущем я исключил некоторые проблемы для себя. Но в таком варианте, как было подмечено нельзя получить путь к файлу, и сохранять нужно как в примере выше.
Я не вспомню почему я остановился на этом способе.
Правильно делать через
Оба способа использовать через Coroutine
Вечно тестить на смарте так себе мысль. Так что вызывать через условие
[UWP] Сохранение JSON в файл
Народ, не подскажете, что не так с этим кодом? После сохранения JSON в файл, добавляется ещё один.
Сохранение строки JSON в файл
Доброго дня. По моему достаточно простая операция, но что то я затупил и не как не могу.
Как можно корректно сохранить html строку в json файл? Например <"id": 1, "html": " style.
Редактирование и сохранение изменений в файл JSON
с записью и чтением все понятно, примеров полно. Подскажите, пожалуйста, как можно редактировать.
Сохранение и Чтения множество картинок в 1 файл совместно с JSON данными
Здравствуйте. Возможно не правильно назвал тему но: Есть класс с данными которые сохраняются в.
Данный код должен реализовывать сохранение в файл имён, но почему-то только создаёт пустой файл. В.
Источник
Сохранение игры в Unity3D
Как это делается в Unity? Вариантов тут достаточно — есть класс PlayerPrefs в библиотеке, можно сериализовать объекты в XML или бинарники, сохранить в *SQL*, можно, в конце-концов, разработать собственный парсер и формат сохранения.
Рассмотрим поподробнее с первые два варианта, и заодно попробуем сделать меню загрузки-сохранения со скриншотами.
Будем считать, что читающий дальше базовыми навыками обращения с этим движком владеет. Но при этом можно не подозревать о сущестовании в его библиотеке PlayerPrefs, GUI, и ещё в принципе не знать о сериализации. С этим всем и разберёмся.
А чтобы эта заметка не стала слишком уж увлекательной и полезной, ориентирована она самый неактуальный в мобильно/планшетно/онлайновый век вариант — сборку под винду (хотя, конечно, более общих моментов достаточно).
- Кстати, пару недель назад на Хабре была статья, где автор упомянул, что Unity3D проходят в курсе компьютерной графики на кафедре информатики питерского матмеха. Занятный факт, немало говорящий о популярности движка.
Хотя насколько это в целом хорошая идея — на мой взгляд, тема для дискуссии. Может быть, обсудить это было бы даже интереснее вопросов сериализации =)
Ещё небольшой дисклеймер — я не профи ни в одной из раскрываемых тем, так что если какие-то вещи можно сделать правильнее-проще-удобнее — исправления и дополнения очень приветствуются.
1. PlayerPrefs
Удобный встроенный класс. Работает с int, float и string. Довольно прозрачный, но мне всё равно встречались на форумах обороты в духе «не могу понять PlayerPrefs» или «надо бы как-нибудь разобраться с PlayerPrefs», так что посмотрим на него на простом примере.
1.1 Примитивное использование в рамках одной сцены: QuickSave & QuickLoad по хоткеям.
Быстрый пример использования. Допустим, у нас одна сцена и персонаж на ней. Скрипт SaveLoad.cs прикреплен к персонажу. Будем сохранять самое простейшее — его положение.
Конечно, тут применение 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 с ней работать удобнее, чем на шарпе, но и на последнем всё в конечном итоге заводится. Кто хочет попробовать, начать можно отсюда.
Этот текст никогда бы не получился без:
и хабра. Спасибо им.
Надеюсь, всё это принесёт кому-нибудь пользу, и никому — вреда 🙂
Источник