For my current project I implemented a component/entity-based system, basically following most of the best-practice there is in this rather undefined area.
So I got (slightly extended) Entities, which are basically an
int ID, a human-readable Name, a
std::map of components and a
long "type indicator" which is used to show what components are present (I have an power of two
enum for all the components types and whenever a component is added to the Entity, I automatically alter that long via bitwise operations, compare this answer).
Then there are the Components, also rather simple:
enum as component type, parent Entity pointer and a
std::map of all properties this component holds.
Lastly some Systems/Managers that handle the actual logic processing. They first check if the currently processed Entity has a matching
long "type indicator" = all necessary components for that system are present. It then accesses some properties if needed and either directly calls some functions in the respective component or send some messages (via a message dispatcher).
Bottom-line: Until here, a rather standard event-driven component/entity-based system combined with a data-driven approach (compare, components do not have hard-coded data variables, but instead a generic map, as (some) components/archetypes of components will later be read from files with the option to add additional data, that is not part of the actual component code.
Now I would like to also introduce Behavior Trees (based on AiGameDev BTSK) into that project, but I am not sure if and how they should be linked to the already existing components or how to integrate those design in general.
Several related ideas/points/questions come to mind:
My BTs will be read from files (again). I currently have a hard time seeing how I would however best make the connection between an
BT Actionin that tree and the actual coding in my application. Should I build up some sort of map between the action names used in the BT files and a function pointer to the actual logic implementation? What is the usual approach to solve that?
I assume that I will have to create BTs for all my different
Entitytypes (so for each game-logic/AI-relevant combination of components as indicated by my multiple times mentioned long "type indicator"). As a result it doesn't make sense to put the
BT Actionimplementations in the components as most likely many components will be involved per action, does it?
So should the
BT Actionlogic sit in a/multiple separate systems (to whose methods the map from idea #1 points to)? The system would then check per my
long"type indicator" whether the
Entityfor which the BT is currently checked and that was told to execute a certain action (= method in the system) is actually allowed to do so (= has the necessary components). But then, if not (because for example the BT creator did overlook a specific situation, where a necessary component might not be attached to the Entity at runtime anymore), nothing would happen.
- Are there proven concepts for that kind of integration?
- What is your take on my 3 points above?
- Any other things that come to mind, also regarding my component/entity-based design in general?