ecsproto-qol
Описание
Языки
- C#100%
LeoECS Proto QoL
Набор расширений для , призванных улучшить "качество жизни" (Quality of Life) разработчика.
ВАЖНО! Требует C#9 (или Unity >=2021.2).
ВАЖНО! Зависит от: Leopotam.EcsProto.
ВАЖНО! Не забывайте использовать
-версии билдов для разработки иDEBUG-версии билдов для релизов: все внутренние проверки/исключения будут работать только вRELEASE-версиях и удалены для увеличения производительности вDEBUG-версиях.RELEASE
ВАЖНО! Проверено на Unity 2021.3 (не зависит от нее) и содержит asmdef-описания для компиляции в виде отдельных сборок и уменьшения времени рекомпиляции основного проекта.
Социальные ресурсы
Официальный блог: https://leopotam.ru
Установка
В виде unity модуля
Поддерживается установка в виде unity-модуля через git-ссылку в PackageManager или прямое редактирование :
"ru.leopotam.ecsproto-qol": "https://gitverse.ru/leopotam/ecsproto-qol.git",
В виде исходников
Код так же может быть склонирован или получен в виде архива со страницы релизов.
Прочие источники
Официальная работоспособная версия размещена по адресу https://gitverse.ru/leopotam/ecsproto-qol, все остальные версии (включая nuget, npm и прочие репозитории) являются неофициальными клонами или сторонним кодом с неизвестным содержимым.
Итераторы
Инициализация
Итераторы получили возможность инициализации 3 способами (итератор по сущностям с компонентами C1 и C2, но без C3):
Если нужен итератор без исключений компонентов, для этого существует отдельный тип:
ВАЖНО! Рекомендованный способ - первый, с использованием
. Варианты с обобщениями более лаконичны, но на большом количестве компонентов и их комбинаций увеличивают размер исполняемого файла.It.List()
Итераторы с кешированием
Если точно известно, что выборка данных не поменяется и требуется обработать ее несколько раз, то можно воспользоваться кеширующими итераторами:
ВАЖНО! Если не вызвать
, то будет брошено исключение в DEBUG-версии.it.BeginCaching()
ВАЖНО! Если был вызван
, в пару ему обязательно вызыватьit.BeginCaching()после завершения обработки, иначе зависимые пулы останутся в режиме ReadOnly. Вызовы не обязательно должны быть в одном методе и даже в одном цикле обработки если работа с заблокированными пулами допускает их работу в ReadOnly-режиме продолжительное время.it.EndCaching()
ВАЖНО! Если не требуется обработка в несколько проходов (например, только 1 итерация), то вариант с кешированием будет работать медленнее.
ВАЖНО! Если требуется проверить режим работы итератора (кешируется или нет), то для этого существует метод
.it.IsCached()
Если есть необходимость получить закешированные сущности в виде непрерывного массива, то можно воспользоваться следующим способом:
Кеширующие итераторы поддерживают сортировку сущностей на основе данных их компонентов:
ВАЖНО! Для уменьшения аллокаций для обработчиков сортировки вместо лямбд рекомендуется использовать локальные функции или методы систем.
Сущности
Упаковка сущностей
Сущности отдаются в пользовательский код в виде -идентификаторов и валидны только в пределах
текущего метода - нельзя хранить ссылки на сущности если нет уверенности, что они не могут быть
уничтожены где-то в коде.
Если требуется сохранять сущности, то их следует упаковать:
Если используется несколько миров и важно сохранять привязку к ним, то можно упаковывать другим способом:
Для сравнения двух упакованных сущностей следует применять оператор :
То же самое касается и упаковки сущности с миром:
Эмуляция апи сущностей из classic-версии
ВАЖНО! Это апи значительно медленнее штатного и не должно использоваться на большом количестве сущностей.
Реализуется через специальный тип :
Так же возможно преобразовать любую активную -сущность в и обратно:
ВАЖНО! Любые операции с
возможны только после проверки ее активности черезProtoSlowEntity.ProtoSlowEntity.IsAlive()
ВАЖНО! Поведение
иProtoSlowEntity.Add()отличается от поведенияProtoSlowEntity.Get()вEcsEntity.Get()- в случае отсутствия запрошенного компонента в мире пул для него не будет создан, а упадет исключение. Запрашивать можно только компоненты, зарегистрированные через аспекты мира.LeoECS Classic
Миры
Инъекции полей в аспекте
Для сокращения количества кода инициализации аспекта мира можно использовать наследование от специального типа - поддерживается инъекция полей, реализующих , и :
Это идентично следующему коду:
Если нужна дополнительная кастомная инициализация, то можно выполнить ее через перегрузки методов /:
Поля могут быть проинициализированы экземплярами данных до начала инъекции - в этом случае они будут использоваться для дальнейшей настройки, это один из способов вызова кастомных конструкторов пулов и аспектов.
Для получения ссылки на мир аспекта можно воспользоваться специальным методом:
Создание авто-итератора из пулов аспекта
Возможно автоматическое создание итератора из полей-пулов , для этого их следует пометить специальными атрибутами:
Использовать авто-итератор аспекта можно следующим образом:
ВАЖНО! Авто-итератор будет создан только в случае наличия в аспекте хотя бы одного пула, отмеченного атрибутом
.[Include]
Список активных сущностей
Если требуется узнать только количество активных сущностей (быстрее):
Список компонентов на сущности
Системы
Инъекции полей в системы
Для инъекции в поля систем их достаточно пометить атрибутом :
ВАЖНО! Инъекция итератора подразумевает, что его экземпляр уже создан через инициализатор поля.
ВАЖНО! Так же поддерживается инъекция
-типа через атрибутProtoWorld, но для оптимизации рекомендуется использовать вызов[DI]. Прямая инъекция может быть полезна для инициализации полей сервисов.ProtoAspectInject.World()
Для корректной работы инъекции в поля систем необходимо подключить специальный модуль:
ВАЖНО! Модуль инъекций должен идти до регистрации остальных модулей и систем, использующих его - проще ставить его всегда самым первым. Подключать модуль нужно только один раз для каждой группы систем.
Существует возможность изменения поведения штатной инъекции, для этого следует подключить специальный сервис с указанием обработчика:
Технически, можно выполнять инъекции в поля не только систем, но и любых объектов через вызов метода :
Можно выполнять инъекцию в подключенные сервисы автоматически, указав опциональный флаг в конструкторе :
Удаление всех компонентов нужного типа
Можно автоматизировать удаление компонентов определенного типа в нужном месте:
поддерживает указание мира для удаляемых компонентов и именованную точку вызова через явное указание дополнительных параметров.
Если этот метод-расширение не устраивает и нужно получить поведение в виде системы - можно воспользоваться ручным созданием экземпляра системы - расширение является оберткой над ней.
Дополнительная инициализация сервисов
Можно автоматизировать дополнительную инициализацию сервисов в нужном месте без создания дополнительных систем:
Чтобы сервис поддерживал дополнительную инициализацию, он должен реализовывать специальный интерфейс:
поддерживает указание именованной точки вызова через явное указание дополнительного параметра.
Если этот метод-расширение не устраивает и нужно получить поведение в виде системы - можно воспользоваться ручным созданием экземпляра системы - расширение является оберткой над ней.
Дополнительная деинициализация сервисов
Можно автоматизировать дополнительную деинициализацию сервисов в нужном месте без создания дополнительных систем:
Чтобы сервис поддерживал дополнительную деинициализацию, он должен реализовывать специальный интерфейс:
поддерживает указание именованной точки вызова через явное указание дополнительного параметра.
Если этот метод-расширение не устраивает и нужно получить поведение в виде системы - можно воспользоваться ручным созданием экземпляра системы - расширение является оберткой над ней.
Пулы
Запрос или добавление компонентов
Для того, чтобы запросить существующий компонент или добавить новый в случае его отсутствия, можно воспользоваться следующим методом:
Безопасное удаление компонентов
Для того, чтобы удалить произвольный компонент на сущности, нужно выполнить предварительную проверку на его существование, либо воспользоваться следующим методом:
Модули
Инициализация
По умолчанию аспекты модуля регистрируются в мире отдельно. Для упрощения одновременной регистрации аспектов, систем и сервисов модуля можно использовать специальный класс:
ВАЖНО! Если используется
- регистрация отдельных модулей черезProtoModulesне рекомендуется, все модули должны проходить черезIProtoSystems.AddModule()единообразно.ProtoModules
Утилиты
Сервис-локатор
Экземпляра класса можно сохранить глобально:
Экземпляра сохраненного глобально класса можно получить в любом месте:
ВАЖНО! Если данные больше не нужны - следует сбросить ссылку на них путем передачи
в метод Set().null
Лицензия
Расширение выпускается под лицензией MIT-ZARYA, подробности тут.