tgoop.com/logofalprog/47
Last Update:
Что-то вроде ECS, но вообще не оно
#код
Этот пост я пишу из Исландии. Коротко сформулировать впечатления от этой страны можно так: красиво, но бессмысленно. Это не в обиду исландцам сказано, просто здесь меня постоянно преследует немой риторический вопрос «зачем вообще селиться на этом суровом куске земли?» Местность вокруг часто больше походит на терраформированный Марс, чем, собственно, на Землю. Но сейчас я «под куполом», то есть в тёплой гостинице, а потому хочется поговорить о чём-то противоположном: пусть не очень красивом, но зато функциональном.
Таковой является, например, наша компонентная система. Последние полгода стоит кому-нибудь заговорить о компонентах, как все сразу вспоминают ECS (Entity Component System), и на первый взгляд то, что написал я, довольно похоже; но на самом деле не имеет с ним ничего общего.
Но давайте по порядку. В Unity много лет были GameObject’ы, которые содержали Component’ы. Это привычная всем, но неэффективная модель. Некоторые даже ошибочно называли её ECS, хотя ей там и не пахло. Настоящая же ECS предполагает 3 вещи: это, собственно, Entity (сущность), Component и System. Причём Entity, в отличие от GameObject’ов — это не объекты. Это просто целочисленные id. То есть просто номера сущностей, которые сами по себе никаких компонентов не хранят. Напротив, каждый компонент «знает», к какой сущности он закреплён. И что немаловажно, компоненты одного типа лежат в одном месте (в одном массиве) и представляют собой только данные. А вся логика находится в системах, которые обрабатывают компоненты только определённого типа. Таким образом логика всегда сводится к тому, чтобы пробежаться по одному или нескольким массивам компонент и выполнить над каждым элементом какие-то однообразные задачи. Благодаря тому, что однотипные данные лежат в памяти друг за другом последовательно, эта задача прекрасно параллелится за счёт векторизации и крайне cache-friendly, что очень и очень хорошо для производительности. В этом и есть основная суть ECS.
В Unity для её внедрения привлекли самого Майка Актона (одного из самых главных идеологов Data oriented design и ECS в частности). Я не смотрел, что у них в итоге получилось, но судя по имени, там теперь действительно всё грамотно в кои-то веки. Но мы стартовали проект, когда этого ещё не было в стабильной версии Unity, поэтому начали разработку на своих компонентах.
У нас тоже есть Entity, но это не номера, а полноценные объекты, которые содержат наши компоненты (мы их зовём модули), а систем нет вообще. По сути это больше даже похоже на старую модель компонентов Unity и тоже совершенно не про производительность. Зачем же тогда надо было это переизобретать? Дело в том, что одним из самых первых и главных стратегических решений в Encased было как можно сильнее отвязаться от сцен и gameobject’ов. Наши Entity и модули — это данные в чистом виде. Игра может играть сама в себя безо всякой визуализации (с небольшими оговорками), а также легко и безболезненно сохранять или загружать своё состояние. С gameobject’ами, как вы понимаете, это сделать было бы в разы сложнее, так как сериализация в Unity это та ещё Песнь пламени и льда (про наше решение как-нибудь напишу отдельный пост). А вся визуализация у нас происходит за счёт размещения на сцене Actor’ов, которые «играют» роль сущностей. У актора на каждый тип модуля сущности есть ModuleSync (если это необходимо), который синхронизирует визуальное представление. Причём могут быть различные Sync для Play- и EditMode.
Таким образом мы минимально завязаны на Unity, минимально имеем оверхедов от её классов, но при этом у нас удобная компонентная система. Потенциально удобная в первую очередь для дизайнеров, так как объекты в RPG играх могут содержать самые разные сочетания свойств, так что без чего-то подобного делать такой проект крайне сложно. К тому же недавно мы добавили возможность наследования компонент от родительской сущности, что теперь позволяет делать шаблоны оружия или предметов прямо на базе компонентной системы.
Обсудить
BY Log of Alprog
Share with your friend now:
tgoop.com/logofalprog/47