Сохранить 16 000 000 объектов в файл сохранения?

Программирование на Юнити.

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Инженер 19 апр 2020, 15:16

Cr0c писал(а):Можно же вручную брать из структуры массив байт ((де)сериализатор написать).
Я, когда-то давно, писал такой. У меня первая версия была по 20 кб на запись, а шестая 50+ кб на 100 записей.


Это интересно, но для меня- темный лес. В какую сторону копать? Туториалы, примеры?


Tolking писал(а):Инженер, Используй эту процедуру для заполнения данных и расскажи нам про объём...
Синтаксис:
Используется csharp
 
   public void SetValue()
    {
        this.allData = "";
        for (int i = 0; i < 11; i++)
        {
            if (this.allData != "") this.allData += " ";
            this.allData += Random.Range(1000000000, 2000000000).ToString();
        }
    }
 


P.S. Странный ты... Используешь потоки, пространство имен, знаешь как обозначается время поиска элемента в массиве, опять же сериализация вместо сохранения и при этом задаешь наивные вопросы... Уж не троль ли ты жЫрный?


140 мб. Ну да, это была глупая надежда =p~ Просто хотелось понять, в чем дело. Ссылочный тип, теперь все ясно. Я не проф. программист, это мое хобби по вечерам. Поэтому нет глубокого понимания темы :)


На днях обдумал обходные пути для решения проблемы огромного размера данных, т.к. одним лишь переводом float в byte вопрос не решить. Если есть еще идеи, милости прошу дополнить.

1. Ограничить размер мира до 1-2 км2.
МИНУСЫ: слишком мало.
ОЦЕНКА: вряд ли.

2. Уменьшить количество сериализуемых объектов. Это приведет к обнулению состояния некоторых объектов, от которых игрок отойдет на небольшое расстояние. Например, не сохранять выкошенную траву.
МИНУСЫ: теряется фишка игры.
ОЦЕНКА: если не хранить в файле данные о каждом пучке травы, это уменьшит размер файла в разы. 16 млн объектов брались как раз из расчета на то, чтобы запоминать положение каждого пучка травы. Нужно найти другой вариант, как запомнить, где игрок выкосил траву. Например, с помощью маски, триггера или типа того. Триггеры можно со временем удалять, типа трава выросла обратно и держать их на сцене постоянно, ограничив количество. Иначе не получится строго контролировать количество триггеров и файл сохранения раздуется. Можно найти другие типы второстепенных объектов, которые не сериализовывать.

3. Уменьшить количество сохраняемых значений у объектов.
МИНУСЫ: уменьшать некуда.
ОЦЕНКА: нет.

4. Сохранять каждый чанк мира в отдельном файле, а не в одном общем. Подгружать по мере необходимости асинхронно. Например, кусками 100х100 метров.
МИНУСЫ: чтение/запись даже в отдельном потоке иногда вызывает лаги. Необходимость перепроектирования уже работающей системы, рассчитанной на цельный файл.
ОЦЕНКА: в целом вариант может оказаться рабочим. Но не известно, можно ли решить проблему с лагами. Нужны тесты. Оставлю на крайний случай, если варианта 2 будет не достаточно.

5. Хранить большую часть значений каждого объекта или групп объектов в отдельном файле. Либо хранить все значения каждого объекта в отдельных файлах, т.е. файл мира содержит только ссылки на другие файлы.
МИНУСЫ: постоянно дергать жесткий диск подгрузкой и сохранением сотен микро файлов, даже в отдельном потоке могут быть лаги. Если сохранять в 2 файла (трансформы + параметры), нет выигрыша по памяти. Если группами, то выигрыш есть, но тогда уж лучше весь мир разбить на отдельные файлы (вариант 4). Плюс необходимость перепроектировать уже созданную систему.
ОЦЕНКА: нет.

6. Создать свой (де)сериализатор, как сказал Cr0c. Уменьшит размер файла и время сохранения/загрузки игры.
МИНУСЫ: Не поможет уменьшить объем данных в оперативке. Сложно.
ОЦЕНКА: Займусь, если найду достаточно информации по этой теме.
Инженер
UNIт
 
Сообщения: 88
Зарегистрирован: 22 май 2016, 11:13

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение 1max1 19 апр 2020, 15:45

Вот этим методом 42 мб превращаются в 4 мб https://metanit.com/sharp/tutorial/5.7.php
Не знаю нюансов, просто первая ссылка в гугле по сжатию данных)
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Cr0c 19 апр 2020, 16:09

1max1 писал(а):Вот этим методом 42 мб превращаются в 4 мб https://metanit.com/sharp/tutorial/5.7.php
Не знаю нюансов, просто первая ссылка в гугле по сжатию данных)

Здесь не лучше:
1. Большой размер данных, иначе сжатие неэффективно
2. Загрузка всех данных в память (нельзя маппить данные в файле и подгружать нужные)
3. Лаг от загрузки не меняется
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Cr0c 19 апр 2020, 16:13

Инженер писал(а):6. Создать свой (де)сериализатор, как сказал Cr0c. Уменьшит размер файла и время сохранения/загрузки игры.
МИНУСЫ: Не поможет уменьшить объем данных в оперативке. Сложно.
ОЦЕНКА: Займусь, если найду достаточно информации по этой теме.

Относительно несложно, позволит маппить внутри файла чанка (либо держать байт-массив как запись в БД), что позволит загружать только необходимые чанки. Разве что добавить id чанка и id соседей
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Cr0c 19 апр 2020, 16:17

Инженер писал(а):Ссылочный тип, теперь все ясно. Я не проф. программист, это мое хобби по вечерам. Поэтому нет глубокого понимания темы :)

Типы данных - это базовое знание языка!
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Dewa1s 21 апр 2020, 09:35

Довелось ковыряться с большим миром на юнити, поэтому напишу пару мыслей, может автору поможет.

1. На таком большом количестве объектов будет захлебываться оклюжн кулинг. Мир в любом случае придется рубить на куски, чтобы была возможность выключать объекты оптом руками
2. В огромной части локаций игрок может никогда не побывать в рамках текущей игровой сессии. Подумай, стоит ли держать это в памяти.

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

По сути тебе придется писать свое хранилище.
Будет ли оно быстрее того же SQLite ?

Если пойдешь путем Крока и будешь писать сам - в принципе ок, только строки придется выкинуть 100%. Много места занимают, сериализуются хреново, да и лучше использовать 2-4 байтовые Id вместо них.
Стандартный бинарный сериализатор я бы выкинул, проще ручками записывать байты в файл, формат же ты знаешь.
Структуры в этом плане будут намного практичнее классов, можно руками расписать положение байтов у каждого члена, как Толкин выше написал.
Кроме того, их киллер фича - возможность маппить через unsafe прям из массива байт.
Если ты будешь знать, в каком именно месте в файле находится нужный тебе набор байтов для нужной структуры (а это намного проще сделать , когда каждая структура имеет фиксированный размер, строки этому не способствуют. Просто по оффсету сможешь до нужной добраться)- читаешь в память именно его и через unsafe объявляешь нужной тебе структурой. И весь файл читать не придется, и на преобразовании типов сэкономишь.
В общем, тебе будет и больно, и весело все это ковырять. Добро пожаловать в бдсм клуб \m/

Вообще, сначала глянь SQLite, может тебя скорость устроит. И гугловский Protobuf если таки решишь хранить бинарники, он тоже довольно шустрый, но вот под C# если честно не проверял, черт его знает, что там за враппер у них
Аватара пользователя
Dewa1s
Старожил
 
Сообщения: 564
Зарегистрирован: 26 дек 2011, 02:12

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Инженер 27 апр 2020, 12:15

Dewa1s писал(а):Довелось ковыряться с большим миром на юнити, поэтому напишу пару мыслей, может автору поможет....


Благодарю за дополнение. Строки выкинул, заменив ushort'ами, ротэйшн тоже самое. Пока не буду заморачиваться с собственным сериализатором, уж больно тема большая и трудная. Надо почитать теорию, найти примеры, разобраться. А мне еще много всего делать, время не ждет. Сейчас делаю независимый стриминг интерьеров, чтобы внутренности домов загружались, только когда игрок входит в дом. В связи с хаотичным добавлением новых фич, вся архитектура проекта превратилась в кашу, теперь мне надо недельку спокойно порефакторить, не добавляя нового функционала.

Но я буду рад, если ты тыкнешь меня носом прямо в готовый пример, как "ручками записывать байты в файл". Чтобы можно было тупо взять и списать, без особых изменений :) Тогда может прям сейчас запихну все в проект. Чувствую себя попрошайкой, но может тебе (или кому-то еще) это сделать не трудно, а мне сэкономит многие часы жизни, потраченные на поиск нужной информации.
Инженер
UNIт
 
Сообщения: 88
Зарегистрирован: 22 май 2016, 11:13

Re: Сохранить 16 000 000 объектов в файл сохранения?

Сообщение Cr0c 27 апр 2020, 17:26

Создаёшь интерфейс IBinaryData, в котором методы де- и сериализации, реализуешь во всех нужных классах
Синтаксис:
Используется csharp
public interface IBinaryData {
  byte[] Serialize();
  void Deserialize(byte[] data);
}
 

А записывать байт-массив уже можно как угодно - в файл, в БД, отправлять по сети...
Аватара пользователя
Cr0c
Адепт
 
Сообщения: 3035
Зарегистрирован: 19 июн 2015, 13:50
Skype: cr0c81

Пред.

Вернуться в Скрипты

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

Сейчас этот форум просматривают: Yandex [Bot] и гости: 16