How to handle dynamic hierarchical entities in ECS
Asked Answered
T

1

6

Here's the analogy: I have an organism which is composed of cells which can be further composed of a medley of attachments.

What I have currently is a sort of event chain between child/parents to handle attaching and detaching components (which could affect anything along the chain) which doesn't involve ecs at all, they are functions in the entities.

Now I've used event components already (for mouse events on objects). If I wanted the system to be pure, would I create an attach component when I attach components etc? Even then how would I get all the necessary recipients to the system that consumes the component? Is it even worth it to handle it this way instead of a chain of functions? Is there a better way?

Tyika answered 27/7, 2019 at 20:31 Comment(0)
W
9

Disclaimer: I'm not sure I got your question correctly. If it's not, I apologize for the rumor.


In order to handle hierarchies in an ECS, you can use a dedicated component similar to the following:

struct relationship {
    entity_type first{entity_null};
    entity_type prev{entity_null};
    entity_type next{entity_null};
    entity_type parent{entity_null};
    // ... other data members ...
};

Where entity_type is the type you use for your entity identifiers and entity_null is your way to say - this isn't set yet. These two things mostly depends on the actual implementation. As an example, in my own (EnTT) there exists entt::null that is a sort of null entity to use in cases like this one.

Let's consider now a generic node in your hierarchy: * parent is the entity identifier of the parent node, so that you can easily walk a tree (A hierarchy) from a leaf to the root. * first is the entity identifier of the first children, that is the list of leaves or internal nodes of the subtree of which the current identifier is the root node. * prev and next are the entity identifiers of the siblings for the current node.

When you want to visit all the children of a node, you start from the first entity (its first child) and iterate them one at a time by visiting next until it becomes null. When you want to go back from a node to its parent, you can just use parent.

A plus of this solution is that lists of children are implicitly defined in terms of components and you don't have to use an std::vector or similar for them. Therefore, you don't have dynamically allocated memory in your components in order to create a hierarchy.

If you're interested, I've also written a post on this topic. You can read it if you want more details.

Woeful answered 31/7, 2019 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.