Как я сделать это включает в себя хранение индекса обратно к объект из компонента (32 бита). Это добавляет немного служебных данных памяти, но общая нагрузка на память компонента в шахте составляет около 8 байтов, что обычно не так уж плохо для моих случаев использования и около 4 байтов на сущность.
Теперь, когда у вас есть обратный указатель на объект, то, что вы можете сделать, когда удовлетворяете запрос для всех объектов, имеющих 2 или более типов компонентов, является использование параллельных наборов бит.
Например, если вы ищете объекты с двумя типами компонентов, Motion
и Sprite
, то мы начинаем с итерации через компоненты движения и установки связанных битов для объектов, которые им принадлежат.
Далее мы перебираем компоненты спрайтов и ищем биты сущности, уже установленные проходом через компоненты движения. Если индекс сущности появляется как в компонентах движения, так и в компонентах спрайта, мы добавляем объект в список объектов, которые содержат оба.Диаграмма идеи, а также, как распараллелить его и объединить объектные Параллельные битовые массивы:
Это дает вам пересечение множеств в линейное время и с очень маленьким m
(очень, очень дешево работайте на итерации, поскольку мы просто отмечаем и проверяем немного - намного, намного, намного дешевле, чем хеш-таблица, например). Я могу на самом деле выполнить набор пересечений между двумя наборами с 100 миллионами элементов каждый в течение секунды, используя эту технику. В качестве бонуса, с некоторыми незначительными усилиями, вы можете заставить его вернуть объекты в отсортированном порядке для типов кэширования доступа, если вы используете битсет для захвата индексов объектов, принадлежащих двум или более компонентам.
Есть способы сделать это лучше, чем линейное время (Log(N)/Log(64)
), хотя он становится значительно более привлекательным, когда вы можете фактически выполнить множество пересечений между двумя наборами, содержащими сто миллионов элементов каждый за миллисекундой. Вот подсказка:
У меня уже есть то, что в основном оболочка вокруг 'станд :: unordered_map', который добавляет, удаляет и извлекает компоненты из этой карты (и сущности являются идентификаторами в карте), так что вы предлагаете просто изменить тип данных и несколько функций. Отлично! – Freaxy