Skip to content

Relationships between entities (inventory as an example) #24

Open
@jddeal

Description

@jddeal

Curious if you have any recommendations on a good way to handle references between entities, and how to store and access those relationships. In particular, we're looking at this in context of entity inventories.

Originally what we kind of hoped was going to work was a component along the lines of this:

struct Inventory {
    int capacity;
    std::vector<entity_t> items;
};

and then use a system and events to manage adding/removing items to a particular entity. This fell flat on its face because entity_t is defined after the components are.

One easy little change we found out we could make was to expose entityplus::detail::entity_id_t; and then using that in place of entity_t above in the vector. We kept going to see how it plays out, and what we ended up with was this helper function to convert the entityplus::detail::entity_id_t; into entity_t:

template <typename ...CompsAndTags>
inline std::unique_ptr<entity_t> find_entity_by_id(entity_manager_t* manager, entityplus::detail::entity_id_t id)
{
    for (entity_t entity : manager->get_entities<CompsAndTags...>())
    {
        if (entity.id == id)
        {
            return std::make_unique<entity_t>(entity);
        }
    }

    return NULL;
};

and it made for fairly enjoyable access anywhere you wanted to use the entities items

auto inventory = player.get_component<Components::Inventory>();
for (auto iter : inventory.items)
{
    auto item = find_entity_by_id(this->entity_manager, iter.second);

    // now we have a pointer to work with
    item->get_component<Components::Identity>();

    // off we go using the entity
}

We actually ran with that for a little bit and it's been alright, but it feels dirty given that we have to modify entityplus to expose that ID. We're lookin to switch this up, but the best next alternative we can think of is having the Inventory component know nothing about the items and go through our InventorySystem which could maintain a mapping of entities with inventories to the list of item entities, then have a function like std::vector<entity_t> InventorySystem::get_items_for_entity(entity_t) for accessing the items.

The reason we don't like that approach as much is because we lose the ability to fully describe our entity by simply looking at its components. With that approach our component tells us how many items might be in the inventory, but we need to communicate with a system to know what items those actually are.

So I guess what I'm asking is if you have any ideas that might allow for referencing entities from within a component. Or perhaps you know of an entirely different approach that maybe we didn't think of. I did notice you mentioned in #19 kind of this scenario we're talking about, but we're failing to understand how the tag approach would work when we have N entities that could have inventories (N tags?).

Appreciate any thoughts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions