Как получить компонент из шаблонного метода в ECS?

Я разрабатываю то, что будет игровым движком Entity Component System, и у меня возникают проблемы с извлечением компонента из сущности.

Вот моя реализация сущности:

class Entity {
public:
Entity(int l_id);

// ...

template <typename T>
std::shared_ptr<T> GetComponent() { // T = CRender, CInput, etc
for (auto& component : m_components) {
if (typeid(component.second.get()) == typeid(T*)) {
return std::dynamic_pointer_cast<T>(component.second);
}
}
return nullptr;
}

private:
int m_id;
std::string m_name;
std::unordered_map<ComponentType, std::shared_ptr<Component>> m_components;

ComponentType — это класс перечисления, содержащийся в классе Component. Компоненты, на которые указывают сущности, это Component в статическом типе, а CRender, CInput и т. Д. В динамическом типе. То есть у меня есть несколько компонентов как дочерние компоненты класса Component.
Кроме того, я держу горстку smart_pointers для каждого компонента в разных классах.
Идея кода заключается в проверке каждого компонента на карте и проверке типа указателя, на который указывает умный указатель.

Этот метод GetComponent () — это то, что я пытаюсь заставить работать.
Цель здесь — получить любой компонент (CRender для компонента рендеринга и т. Д.), Выполнив что-то вроде этого:

std::shared_ptr renderComponent = entity.GetComponent<CRender>();

Мне трудно понять, как это сделать, так как я храню компоненты на карте, так что может быть только 1 компонент каждого типа.

Что я делаю неправильно? Также я бы приветствовал любые лучшие идеи дизайна реализации, которые у вас могут быть. Заранее спасибо!

0

Решение

Это, кажется, проблема здесь:

if (typeid(component.second.get()) == typeid(T*))

Основная проблема заключается в том, что typeid при использовании с указателями вы не получите производного типа, как вы ожидаете. Это даст вам typeid «указатель на компонент», так что вы всегда будете оценивать typeid(pointer-to-Component) == typeid(pointer-to-DerivedComponent),

Что касается улучшений, в вашем коде вы не используете поиск по ключевым функциям std::map, Вместо циклического перемещения по карте вы можете изменить функцию GetComponent на не шаблонную функцию, которая принимает значение перечисления в качестве параметра и использует его для поиска карты.

Поскольку вы изначально написали шаблонную функцию, в качестве альтернативы вы могли бы выиграть от изменения типа ключа вашей карты на std::type_index, Это позволит вам сделать:

std::map<std::type_index, std::shared_ptr<Component>> components;

template <typename T>
std::shared_ptr<T> GetComponent() {
return std::dynamic_pointer_cast<T>(components[typeid(T)]);
}

И вы должны включить логику для обработки случая, когда компонент не найден, как вы делаете в своем исходном коде.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector