LOGOFALPROG Telegram 49
Сериализация. Часть 1: Предисловие
#кодище
На прошлый мой пост были комментарии в чатике о том, что как-то слишком заморочено всё у меня. Поэтому я решил вас не томить, и начать уже рассказывать о действительно мудрёной системе — о нашей сериализации. Здесь уж ни в какие лимиты 4000 знаков я точно не влезу, поэтому рассказ будет разбит на несколько частей.

Начнём с предисловия. Пожалуй, самая сложная проблема создания RPG с пошаговым боем с точки зрения кода — это сохранение игры. Действительно, здесь почти нет ничего реалтаймового, что нужно как-то синхронизировать или тяжело отлаживать, как в каком-нибудь физическом платформере или мультиплеерном шутере; но зато при сохранении игры нельзя обойтись банальными чекпоинтами или ручным сохранением координат объектов. Нужно честно и автоматически уметь сохранять весь мир. Можно делать это дампом памяти или через сериализацию, но так или иначе, организация всего остального кода будет плясать от того, как мы сохраняем данные. Поэтому об этом надо думать на самых ранних этапах проекта.

Первым делом, конечно, проверил, не поменялось ли чего в стандартной сериализации Unity. А там без изменений: мрак и тихий ужас. Плохо всё: жёсткая привязка к UnityScriptableObject, нет поддержки абстрактных или базовых классов (то есть никакого наследования, только конкретные типы), нет поддержки свойств, отвратительный резолвер ссылок, который всегда резервирует место под целый объект. А если объект содержит ссылки на объект того же типа, то резервирует место до 7 уровня вложенности. А это выделение места под 2187 объектов только для трёх ссылок (3⁷)! Я правда не понимаю, как на этом можно делать что-то сколько бы то ни было серьёзное.

Расширять это безумие можно только жутчайшими костылями в виде скрытого string поля, которое заполняется байтами и парсится самостоятельно на ISerializationCallback’и. Именно так поступает популярный плагин Odin, на которого я поначалу возлагал большие надежды. Да, приходится наследоваться от его классов; да, твои классы от этого пухнут байт на 20 каждый (даже мелкие), но я готов был мириться даже с этим, лишь бы это сэкономило нам время, если бы не одно «но». Как выяснилось, поддержка сериализации свойств в Odin’е распространяется только на auto-properties, то есть на те свойства, что имеют дефолтный геттер и сеттер; а никаких кастомных действий в сериализацию пропихнуть не удастся. Без чего вся затея теряет всякий смысл. И это, заметьте, самое лучшее решение из Asset Store, которое сами Unity Technologies отмечали. Так что от него и ему подобных пришлось отказаться.

В этом месте средний программист прикрутил бы первую попавшуюся json-библиотечку (и потом бы мучался с ней в той или иной степени), но большинство из них меня по разным причинам не устраивали: где-то нет исходников, где-то уродская атрибуция, где-то нет бинарного формата. А если и есть, то имена полей всё равно пишутся много раз текстом в файл.

То ли дело Protobuf (протокол сериализации от google), который решает все эти проблемы и даже больше. Для тех, кто не знает, его фишка в том, что все сериализуемые поля класса помечаются атрибутом с уникальным номером. Привязка полей идёт именно по этому номеру, поэтому можно спокойно переименовывать, добавлять или удалять любые поля, не беспокоясь при этом об обратной совместимости сейвов. К тому же я уже работал с ним в .Net и горя не знал (кроме пары мелочей). Но беда пришла откуда не ждали. Мне потребовалось сделать условную сериализацию: ноды верхнего уровня сериализуются полностью, а вложенные объекты сохраняются как ссылки (об этом в следующих частях). И в protobuf просто не оказалось способа задать такое поведение без копипаста или появления лишнего редиректа. Казалось бы, не бывает слова «нельзя» — возьми исходники да поправь — но выяснилось, что dll написана на C# 7, а в Unity даже 6 был тогда только в бете. Пересобирать её каждый раз на стороне жуть как не хотелось, поэтому я продолжил поиски.

To be continued… Обсудить



tgoop.com/logofalprog/49
Create:
Last Update:

Сериализация. Часть 1: Предисловие
#кодище
На прошлый мой пост были комментарии в чатике о том, что как-то слишком заморочено всё у меня. Поэтому я решил вас не томить, и начать уже рассказывать о действительно мудрёной системе — о нашей сериализации. Здесь уж ни в какие лимиты 4000 знаков я точно не влезу, поэтому рассказ будет разбит на несколько частей.

Начнём с предисловия. Пожалуй, самая сложная проблема создания RPG с пошаговым боем с точки зрения кода — это сохранение игры. Действительно, здесь почти нет ничего реалтаймового, что нужно как-то синхронизировать или тяжело отлаживать, как в каком-нибудь физическом платформере или мультиплеерном шутере; но зато при сохранении игры нельзя обойтись банальными чекпоинтами или ручным сохранением координат объектов. Нужно честно и автоматически уметь сохранять весь мир. Можно делать это дампом памяти или через сериализацию, но так или иначе, организация всего остального кода будет плясать от того, как мы сохраняем данные. Поэтому об этом надо думать на самых ранних этапах проекта.

Первым делом, конечно, проверил, не поменялось ли чего в стандартной сериализации Unity. А там без изменений: мрак и тихий ужас. Плохо всё: жёсткая привязка к UnityScriptableObject, нет поддержки абстрактных или базовых классов (то есть никакого наследования, только конкретные типы), нет поддержки свойств, отвратительный резолвер ссылок, который всегда резервирует место под целый объект. А если объект содержит ссылки на объект того же типа, то резервирует место до 7 уровня вложенности. А это выделение места под 2187 объектов только для трёх ссылок (3⁷)! Я правда не понимаю, как на этом можно делать что-то сколько бы то ни было серьёзное.

Расширять это безумие можно только жутчайшими костылями в виде скрытого string поля, которое заполняется байтами и парсится самостоятельно на ISerializationCallback’и. Именно так поступает популярный плагин Odin, на которого я поначалу возлагал большие надежды. Да, приходится наследоваться от его классов; да, твои классы от этого пухнут байт на 20 каждый (даже мелкие), но я готов был мириться даже с этим, лишь бы это сэкономило нам время, если бы не одно «но». Как выяснилось, поддержка сериализации свойств в Odin’е распространяется только на auto-properties, то есть на те свойства, что имеют дефолтный геттер и сеттер; а никаких кастомных действий в сериализацию пропихнуть не удастся. Без чего вся затея теряет всякий смысл. И это, заметьте, самое лучшее решение из Asset Store, которое сами Unity Technologies отмечали. Так что от него и ему подобных пришлось отказаться.

В этом месте средний программист прикрутил бы первую попавшуюся json-библиотечку (и потом бы мучался с ней в той или иной степени), но большинство из них меня по разным причинам не устраивали: где-то нет исходников, где-то уродская атрибуция, где-то нет бинарного формата. А если и есть, то имена полей всё равно пишутся много раз текстом в файл.

То ли дело Protobuf (протокол сериализации от google), который решает все эти проблемы и даже больше. Для тех, кто не знает, его фишка в том, что все сериализуемые поля класса помечаются атрибутом с уникальным номером. Привязка полей идёт именно по этому номеру, поэтому можно спокойно переименовывать, добавлять или удалять любые поля, не беспокоясь при этом об обратной совместимости сейвов. К тому же я уже работал с ним в .Net и горя не знал (кроме пары мелочей). Но беда пришла откуда не ждали. Мне потребовалось сделать условную сериализацию: ноды верхнего уровня сериализуются полностью, а вложенные объекты сохраняются как ссылки (об этом в следующих частях). И в protobuf просто не оказалось способа задать такое поведение без копипаста или появления лишнего редиректа. Казалось бы, не бывает слова «нельзя» — возьми исходники да поправь — но выяснилось, что dll написана на C# 7, а в Unity даже 6 был тогда только в бете. Пересобирать её каждый раз на стороне жуть как не хотелось, поэтому я продолжил поиски.

To be continued… Обсудить

BY Log of Alprog


Share with your friend now:
tgoop.com/logofalprog/49

View MORE
Open in Telegram


Telegram News

Date: |

The public channel had more than 109,000 subscribers, Judge Hui said. Ng had the power to remove or amend the messages in the channel, but he “allowed them to exist.” 4How to customize a Telegram channel? Telegram is a leading cloud-based instant messages platform. It became popular in recent years for its privacy, speed, voice and video quality, and other unmatched features over its main competitor Whatsapp. Ng Man-ho, a 27-year-old computer technician, was convicted last month of seven counts of incitement charges after he made use of the 100,000-member Chinese-language channel that he runs and manages to post "seditious messages," which had been shut down since August 2020. Select “New Channel”
from us


Telegram Log of Alprog
FROM American