ECS - проблема коллизии сущностей при подгрузке и выгрузке игровых объектов
Дисклеймер: вопрос относится к тем реализациям ECS, где entity - это идентфикатор представленный парой целых чисел - index и generation. При этом index переиспользуется, и в каждый момент времени не должно существовать несколько живых сущностей с одинаковыми индексами.
В чем собственно проблема: при выгрузки игровых объектов - мы сохраняем их компоненты и сущности на диск, а затем удаляем их из игрового мира. Идентификаторы выгруженных игровых объектов могут быть переиспользованы. При подгрузке ранее выгруженного объекта мы получаем потенциальный конфликт двух живых сущностей с одинаковыми индексами.
Вопрос: как нам избежать потенциального конфликта двух живых сущностей с одинаковыми идентификаторами?
Текущие решения, которые меня не устраивают:
- не удалять entity из игрового мира при выгрузке сущностей. Решение самое простое, но если игровая карта больших размеров с кучей объектов - в какой-то момент entity начинают отжирать нормально так памяти.
- вместо entity сохранять их алиасы (например UUID) и при подгрузке, для каждого игрового объекта создавать новую entity. Тут проблема с сылочной целостностью. Entity могут использоваться внутри компонентов, когда одной сущности надо ссылатсья на другую. Придется просмотерть все компоненты и поменять старую entity на новую. Это геморно и чревато трудно-отлавливаемыми багами.
- UPD Выгужать entity из памяти, но оставлять инфорацию о зарезервированном индексе выгруженной сщуности. Эти данные можно хранить в битовом векторе, что вполне компактно (1 бит на сущность). Но при большом кол-ве сущностей (сотни миллионов или миллиарды) - даже битовый вектор начинает отжирать неприлично много памяти. Такое кол-во сущностей может встретиться на каких-нибудь старых онлайн серверах, особенно в играх-песочницах (как пример - 2b2t). Но что хуже всего - при таком подходе мы перестаем переиспользовать большинство сущностей.
Ответы (1 шт):
По итогу мне удалсь найти два универсальных варианта:
Отдельная модель для хранения игровых объектов.
Связи между объектами не хранятся в виде сущностей. Для каждого загружаемого объекта создаётся новая сущность. Такой подход я уже упоминал в вопросе.
Отказ от идеи переиспользуемых идентификаторов для сущностей.
В этом случае сущность представляется уникальным идентификатором (например, UUID или просто числом из глобального счётчика). Такой подход менее производителен, но зато не требует поддержки нескольких моделей для одной и той же бизнес-сущности.