How to index all the derived components in a base component list in Entity

老子叫甜甜 提交于 2020-01-02 12:20:13

问题


I am trying to do a entity component system design for simulation. Here is what confuses me now. I am trying to make a Entity class

Entity.h
class Entity
{
public:
    Entity();
    virtual ~Entity() = 0;
    //---------------------Methods---------------------//
    void AddComponent(const shared_ptr<Component> component);

    template<class T>
    T* GetComponent() const;

    //---------------------Members---------------------//
    vector<shared_ptr<Component>>   m_components;
}

Entity.cpp
template<typename T>
T* Entity::GetComponent() const
{
    Component::component_type_t typeIndex = /*T::component_type*/
    T* returnPtr = dynamic_pointer_cast<T>(m_components[component_type].get());
    return returnPtr;
}

And the Component class looks like this

class Component
{
public:
    Component();
    virtual ~Component() = 0;
    //---------------------Methods---------------------//

    //---------------------Members---------------------//
    typedef enum component_type_t
    {
        MESH_T,
        RIGIDBODY_T,
        TRANSFORM_T,
        NUM_TYPES
    };
    component_type_t componentType;
};

They way I want to use GetComponent() is the same as in Unity3D

Transform* t = GetComponent<Transform>()

But as you can see I cannot find a way to do that yet. The way I used to do it was

class Entity
{
    .....
    Component* GetComponent(Component::component_type_t componentType) const
    {
      return m_components[component_type].get()
    };
}

And I could only use it as

Transform* t = dynamic_pointer_cast<Transform>(GetComponent(Component::component_type_t::TRANSFORM_T));

Clearly it is tedious.

So my question is can I use some form as this?

class Entity
{
    .....
    template<class T>
    T* GetComponent() const
    {
    Component::component_type_t typeIndex = /*T::component_type*/
    T* returnPtr = dynamic_pointer_cast<T>(m_components[component_type].get());
    return returnPtr;
    };
}

I feel the cleanness and the speed to keep using std::vector<> for storing all my component pointers, is that also a valid design?


回答1:


Did something similar long time ago. I think you are doing this the hard way. You can easily modify the code below to suit your need. The Components are inherited. You can remove the inheritance and replace it with class inside class or all component classes inside the Component class.

#include <iostream>

struct Vector3
{
    float x, y, z;
    Vector3(float x, float y){}
    Vector3(float x, float y,float z){}
};

template <class T>
class Component
{
public:
    T t;
    void adNewComponent(){

    }
};

class Mesh{
public:
    Mesh(){}
};

class Rigidbody{
public:
    Rigidbody(){}
    void AddForce(float x,float y, float z){}
    void AddForce(Vector3 force){}
};


class Transform{
public:
    Transform(){}
};

class Object{

};

class GameObject:Object,
    Component<Mesh>,
    Component<Rigidbody>,
    Component<Transform>
{
public:
     template <class T>
     T &GetComponent()
    {
        return this->Component<T>::t;
    }

     template <class T>
     T &AddComponent(){
         this->Component<T>::adNewComponent();
         return this->Component<T>::t;
     }
};


int _tmain(int argc, _TCHAR* argv[])
{

    GameObject gameObject;
    gameObject.AddComponent<Rigidbody>();
    Rigidbody rigidBody = gameObject.GetComponent<Rigidbody>();
    rigidBody.AddForce(9,0,0);

    std::cin.get();
    return 0;
}


来源:https://stackoverflow.com/questions/37578849/how-to-index-all-the-derived-components-in-a-base-component-list-in-entity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!