Однажды у меня возникло недоразумение, что «работа - самая быстрая, работа - это справедливость», поэтому даже с такой простой операцией, как уничтожение сущностей по очень простым критериям группы компонентов, я выполнил эту работу.

Плохо: запланировать задание только для того, чтобы поставить в очередь ECB.

Верно, что рабочие потоки - это здорово, но ошибка в том, что ECB. На самом деле EntityCommandBuffer МЕДЛЕННО. Он просто EntityManager выполняет DestroyEntity один за другим позже на барьере в основном потоке, это не значит, что они уничтожаются в работе.

Назначение ECB - отложить EM-команды, а не ускорить EM-команды. А потому эта работа - пустая трата времени.

Так что не имеет значения, запланировали ли вы IJobChunk или что-нибудь с высокой степенью распараллеливания. Командный буфер заставит их произойти позже. И сейчас лучше, чем позже. (По производительности)

Хорошо: просто используйте EntityManager прямо здесь

Даже повторное уничтожение с помощью EM напрямую, наивно, будет быстрее, потому что вы не планируете работу!

Будьте осторожны, чтобы не обесценить то, над чем вы работаете. Использование PostUpdateCommand и повторение уничтожения должно быть быстрее на небольшом количестве сущностей, версия ECB с заданием может выиграть с достаточно большим количеством и большим количеством фрагментов для использования с такими вещами, как IJobChunk? (Это превратилось в гонку команд в очереди)

Лучше: используйте перегрузку NativeArray

Но в любом случае с группой компонентов или NativeArray<Entity> он может уничтожить пакетно в основном потоке.

public void AddComponent(NativeArray<Entity> entities, ComponentType componentType);
public void CreateEntity(EntityArchetype archetype, NativeArray<Entity> entities);
public void DestroyEntity(NativeArray<Entity> entities);
public void Instantiate(Entity srcEntity, NativeArray<Entity> outputEntities);
public void RemoveComponent(NativeArray<Entity> entities, ComponentType type);

Из 5 методов:

Добавить / удалить: это просто итерация по каждому из них и добавление / удаление. (отстой)

Instantiate / Create / Destroy: Похоже, он действительно может создавать и уничтожать в пакетном режиме, чтобы сэкономить время!

Может быть, даже лучше: используйте ExclusiveEntityTransaction

Но если вы действительно хотите уничтожить (или выполнить другие ЭМ операции) в работе, используйте ExclusiveEntityTransaction

EET - это нечто противоположное тому, что обычно происходит. Обычно, чтобы что-то сделать с EM, мы должны на мгновение «вернуться» к основному потоку (на барьерах, в ComponentSystem и т. Д.). С EET мы можем «заблокировать EM» для работы одного потока и предотвратить основной поток. нить от его использования. Но основной поток может продолжать и делать другие вещи, включая планирование большего количества заданий, которые не касаются ЭМ.

Никто в мире не сможет использовать этот EM в основном потоке во время выполнения задания, но другой EM, конечно, работает нормально. Однако один рабочий поток будет недоступен, потому что EET происходит в другом мире. (Давай! Сейчас! Если хочешь!)

Таким образом, использование EET в значительной степени ориентировано на создание нескольких миров. Он делает 1 мир почти непригодным для использования (EM стал занятым на работе), но другие ваши миры могут по-прежнему работать со своими собственными EM и оставшимися рабочими потоками. Теперь вы видите то, чего можно достичь только в нескольких мирах!

Но чтобы сделать несколько миров полезными для друг друга, потребуется более тщательное планирование того, как общаться. (Что, вероятно, принадлежит EntityManager.MoveEntitiesFrom?)

«Выбрасывание», когда другой мир выполняет EntityManager.MoveEntitiesFrom вашего основного мира

Этот метод имеет ComponentGroup перегрузку, которая на первый взгляд запускает задание, которое отсекает запрашиваемые указатели фрагментов и передает его второму EntityManager. Никакой копии или чего-то еще, но с некоторым переназначением сущностей (индекс и версия адаптируются к новому миру). Таким образом, это должен быть самый быстрый способ «избавиться» от кусков, которые вы изначально намеревались уничтожить. (Думаю?)

Помните, что ComponentGroup должно быть создано из мира, владеющего вещами, которые вы хотите переместить! Компьютерная графика не может быть заменена между мирами.

Также эта перегрузка запрашивает у вызывающего NativeArray рабочее пространство переназначения сущностей, которое вы можете получить от EntityManager.CreateEntityRemapArray. У вас будет достаточно размера, чтобы метод работал. (Пожалуйста, сделайте это из EntityManager мира, из которого вы перемещаетесь) В качестве бонуса вы получите результат переназначения обратно, но безопасно просто удалить его немедленно или просто использовать using на EntityManager.CreateEntityRemapArray.

Затем, когда эти куски окажутся в «мире мусора», вы можете использовать EET, чтобы уничтожить их по-настоящему в работе, или просто уничтожить этот мир, должно быть еще быстрее. (Наверное?)

Не только для уничтожения, если вы хотите массово добавить / удалить кучу компонентов с тяжелым условием, например, 10000 объектов, если вы сделаете это в одном мире с одновременным ECB, то при воспроизведении неизбежно остановится все в твой мир.

Может быть лучше переместить эти 10000 сущностей во 2-й мир, где вы можете работать на полную мощность с EET на работе, а ваш 1-й мир тем временем делает что-то еще.

Наконец, когда в вашем 1-м мире заканчиваются дела, если в нем нет обработанных компонентов, переместите их обратно. На этом шаге должно быть немного сложно определить «когда», так как у вас нет цепочки депов JobComponentSystem для управления этой зависимостью за вас. Возможно, положение ComponentSystem, связанное с UpdateAfter всеми системами, которые не требуют обработки вещей во 2-м мире. Затем эта система MoveEntitiesFrom и все другие системы, требующие обработанных сущностей, должны быть согласованы с UpdateAfter этой мировой системой синхронизации. (Использовать UpdateInGroup?)

Самое замечательное: используйте перегрузку ComponentGroup

У ExclusiveEntityTransaction этого даже нет, так что все приветствуют основной поток. Каждый раз, когда вы используете EntityManager, который есть с ComponentGroup, вы делаете это одновременно со всем фрагментом и вызываете нулевое перемещение данных, поскольку все происходит в одном фрагменте! (Несколько фрагментов, даже если у вас столько Entity, что они занимают несколько фрагментов на одном ComponentGroup)

Вот все, что вы можете использовать.

public void RemoveComponent(ComponentGroup componentGroup, ComponentType componentType);
public void AddComponent(ComponentGroup componentGroup, ComponentType componentType);
public void AddSharedComponentData<T>(ComponentGroup componentGroup, T componentData) where T : struct, ISharedComponentData;
public void DestroyEntity(ComponentGroup componentGroupFilter);

VS NativeArray<Entity> перегрузка? Это намного лучше, поскольку такие вещи, как добавление и удаление, действительно происходят во всем фрагменте, и никто не перемещается. Вы даже получаете возможность массового добавления SCD!

Совет от профессионала: он работает даже тогда, когда ComponentGroup .SetFilter тоже был исправлен. Таким образом, вы можете даже выполнять выборочную массовую операцию на основе ваших SharedComponentData или .SetFilterChanged критериев. Только не забывайте .ResetFilter, если хотите, чтобы группа вернулась в нормальное состояние.