Для моего текущего проекта я внедрил систему , основанную на компонентах / сущностях , в основном следуя большинству лучших практик в этой довольно неопределенной области .
Таким образом, я получил (немного расширенный) сущности , которые в основном являются int
идентификатором, понятным для человека именем, std::map
компонентами и long
«индикатором типа», который используется, чтобы показать, какие компоненты присутствуют (у меня есть степень два enum
для всех компонентов типы и всякий раз, когда компонент добавляется к сущности, я автоматически изменяю это долго с помощью побитовых операций, сравните этот ответ ).
Затем есть Компоненты , также довольно простые: int
ID, enum
как тип компонента, указатель родительского Entity и a std::map
всех свойств, которые этот компонент содержит.
Наконец, некоторые системы / менеджеры, которые обрабатывают фактическую логику обработки. Сначала они проверяют, имеет ли обработанный в настоящий момент объект соответствующий long
индикатор типа = присутствуют все необходимые компоненты для этой системы. Затем он получает доступ к некоторым свойствам, если это необходимо, и либо напрямую вызывает некоторые функции в соответствующем компоненте, либо отправляет некоторые сообщения (через диспетчер сообщений).
Итог: до сих пор довольно стандартная система, основанная на событиях, основанная на компонентах / объектах, в сочетании с подходом, управляемым данными (сравните, компоненты не имеют жестко закодированных переменных данных, а вместо этого представляют собой общую карту, как (некоторые) компоненты / архетипы компонентов будут позже прочитаны из файлов с возможностью добавления дополнительных данных, которые не являются частью реального кода компонента.
Теперь я хотел бы также включить Поведенческие деревья (на основе AiGameDev BTSK ) в этот проект, но я не уверен, следует ли и как их связывать с уже существующими компонентами или как интегрировать этот дизайн в целом.
На ум приходит несколько связанных идей / моментов / вопросов:
Мои БТ будут читаться из файлов (снова). В настоящее время мне трудно понять, как лучше установить связь между
BT Action
этим деревом и реальным кодированием в моем приложении. Должен ли я создать какую-то карту между именами действий, используемыми в файлах BT, и указателем функции на фактическую реализацию логики? Каков обычный подход к решению этой проблемы?Я предполагаю, что мне придется создавать BT для всех моих различных
Entity
типов (то есть для каждой игровой логики / AI-соответствующей комбинации компонентов, как указано в моем многократно упомянутом длинном «индикаторе типа»). В результате не имеет смысла помещатьBT Action
реализации в компоненты, так как, скорее всего, в каждом действии будет задействовано много компонентов, не так ли?Так должна ли
BT Action
логика располагаться в нескольких системах (на чьи методы указывает карта из идеи № 1)? Затем система проверила бы по моемуlong
«индикатору типа»,Entity
разрешено ли для этого факту, для которого в настоящее время проверен BT и которому было приказано выполнить определенное действие (= метод в системе) (= имеет необходимые компоненты). Но тогда, если нет (потому что, например, создатель BT действительно упустил из виду конкретную ситуацию, когда необходимый компонент может больше не присоединяться к сущности во время выполнения), ничего бы не произошло.
Вопросов:
- Существуют ли проверенные концепции для такой интеграции?
- Что вы думаете о моих 3 очках выше?
- Любые другие вещи, которые приходят на ум, в том числе касательно моего дизайна компонентов / сущностей в целом?
источник
Ответы:
Забудьте о функциональных указателях и подумайте об объектах. Каждый узел в дереве поведения (BT с этого момента) в идеале должен соответствовать одному объекту в вашем коде. Эти объекты будут иметь стандартный интерфейс, позволяющий вам упорядочить их как дерево и обходить их. Набор указателей на функции хорош для поведения, но он совсем не отражает структуру вашего дерева.
Я ожидаю, что у сущностей будет один компонент BehaviorTree, в котором хранятся соответствующие данные для BT этой сущности. Выполнение BT выполняется компонентом BT или подсистемой BT в зависимости от того, как вы обрабатываете компоненты в вашей системе. Как и почти все, что использует компоненты, им придется обращаться к другим компонентам, чтобы выполнить работу, но эти другие компоненты не должны ничего знать о BT.
Различные доступные действия, на самом простом уровне, будут закодированы в различные объекты узла BT. Они должны быть в состоянии заставить соответствующий объект действовать, манипулируя компонентами по мере необходимости, например. доступ к компоненту движения для перемещения.
источник