ComponentPools problem

Started by
1 comment, last by SeanMiddleditch 9 years, 3 months ago

I have a simple entity manager with pointers to my component pools. My components are simple POC structs. My component pool is a template class.

Components:


#ifndef COMPONENTS_H
#define COMPONENTS_H

#include "Datatypes/vector3.h"

enum MESH_TYPE
{
    STATIC_GROUND_MESH,
    ANIMATED_MESH
};

typedef struct
{
    Vector3 position;
    Vector3 rotation;
} SpatialComponent;

typedef struct
{
    float farClipping;
    Vector3 target;
} CameraComponent;

typedef struct
{
    MESH_TYPE type;
    std::string name;
} MeshComponent;

typedef struct
{
    Vector3 translate;
    Vector3 rotate;
} MovementComponent;
#endif // COMPONENTS_H

ComponentPool:


#ifndef COMPONENTPOOL_H
#define COMPONENTPOOL_H

#include "components.h"
#include "datatypes.h"

#include <boost/container/flat_map.hpp>
#include <algorithm>
#include <vector>
#include <iostream>
#include <climits>
#include <typeinfo>

class ComponentPoolBase
{

};

template <typename T>
class ComponentPool : public ComponentPoolBase, public boost::container::flat_map< EntityId, T >
{
    typedef boost::container::flat_map< EntityId, T > Components_t;

public:
    ComponentPool()
    {
    }

    T& Get(const EntityId& entityId)
    {
        return this->at(entityId);
    }

    int Size()
    {
        return this->size();
    }

    bool Has(EntityId entityId)
    {
        typename Components_t::iterator itr = this->find(entityId);

        if(itr == this->end())
        {
            return false;
        }

        return true;
    }

    bool Add(EntityId entityId)
    {
        try
        {
            this->insert(boost::container::container_detail::pair< EntityId, T >(entityId, T()));

            std::cout << "New component entity id: " << entityId << " Type: " << typeid(T).name() << std::endl;
            std::cout << "Count: " << this->size() << std::endl;
            return true;
        }
        catch (std::exception& ex)
        {
            std::cout << "Exception: " << ex.what() << std::endl;
        }

        return false;
    }

    bool Remove(EntityId entityId)
    {
        try
        {
            this[entityId] = NULL;

            std::cout << "Delete component entity id: " << entityId << " Type: " << typeid(T).name() << std::endl;
            return true;
        }
        catch (std::exception& ex)
        {
            std::cout << "Exception: " << ex.what() << std::endl;
        }

        return false;
    }
};

#endif // COMPONENTPOOL_H

EntityManager:


#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H

#include "Component/componentpool.h"
#include "Component/components.h"
#include "datatypes.h"

#include <iostream>
#include <queue>

class EntityManager
{
    typedef std::queue< EntityId > EntityList_t;

public:
    EntityManager();
    ~EntityManager();

    void Init();
    void Shutdown();

    EntityId CreateEntity(const std::string& name);
    void DestroyEntity(EntityId entityId);

    EntityId GetCreatedEntities();
    EntityId GetRemovedEntities();

    ComponentPool<SpatialComponent>* m_pSpatialComponents;
    ComponentPool<CameraComponent>* m_pCameraComponents;
    ComponentPool<MeshComponent>* m_pMeshComponents;
    ComponentPool<MovementComponent>* m_pMovementComponents;

private:
    EntityList_t* m_pCreatedEntities;
    EntityList_t* m_pRemovedEntities;



    EntityId getNextId()
    {
        return ++s_NextId;
    }

    static EntityId s_NextId;
};

#endif // ENTITYMANAGER_H

My great problem, are the pointers to the ComponentPool. I want to store this in a vector with unique pointer, because the entity manager is the only one, who is responsible for the lifetime of my entites and components.

I thought it should be this way:


std::vector<std::unique_ptr<ComponentPool<ComponentPoolBase*>>> m_ComponentPools;

And I add a unique pointer this way:


m_ComponentPools.push_back(std::unique_ptr<ComponentPool<SpatialComponent>>(new ComponentPool<SpatialComponent>()));

But this doesn't work with a not matching function error in the compiler. Why?

Is there a better solution to implement this component pool and entity manager?

Advertisement

I guess what you want is:


std::vector<std::unique_ptr<ComponentPoolBase>> m_ComponentPools;

There's no need for the pointer type if you store them w/o a vector in your EntityManager, e.g.


ComponentPool<SpatialComponent> m_pSpatialComponents;
What BloodyEpi said.

For things like this where I need a central manager, I tend to make that manager non-owning. i.e. it just stores raw pointers, and someone else is responsible for holding on to the unique_ptr (or just store the thing as a local/member variable).

This also extends into bigger architectures where you might have multiple different places registering things. For instance, as your project grows, you might find that you want to move all the graphics components into a GraphicsService and all the physics components into a SimulationService and so on, rather than making some huge central beast of a manager know about every single type of component.

Sean Middleditch – Game Systems Engineer – Join my team!

This topic is closed to new replies.

Advertisement