问题
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