gpt4 book ai didi

c++ - 如何改进 GetComponent<> 方法

转载 作者:行者123 更新时间:2023-11-28 04:11:40 24 4
gpt4 key购买 nike

我一直在调试另一个问题中的方法,尽管它已被修复,但评论让我相信我做的事情很糟糕,但没有人能够提出如何改进它的建议。

我正在编写的渲染引擎使用受 unity 启发的组件系统。 GetComponent<>()方法从对象返回给定类型的组件(如果存在),并返回 nullptr如果给定的组件不存在。所有组件都继承自一个公共(public)的 Component基类。

代码如下:

template <typename CompType>
inline CompType getComponent()
{
for(Component * currComp : compStruct.components)
{
CompType currentEntry = dynamic_cast<CompType>(currComp);
if (currentEntry != nullptr)
{
return currentEntry;
}
}
return nullptr;
}

用法如下:

//Returns a valid RenderConditions pointer if the object has that component
RenderConditions* rc = go->getComponent<RenderConditions*>();

dynamic_cast显然是不可取的,特别是因为这个系统可以在一个帧中多次用于 RenderComponents、AnimationComponents、Transform 或任何东西。关于为每种类型的组件设置一个固定的“ID”,我有几个想法,但关键是我希望这个游戏引擎的用户能够为系统编写他们自己的组件,并且没有 dynamic_cast我发现它只适用于#included in object.h 的组件

有什么改进的想法吗?

最佳答案

潜在陷阱:

不要使用此方法来存储持久性(例如在磁盘上)类型元数据,因为 typeid 可能会在同一程序的不同调用之间发生变化。


附带说明:在 Unity 中,GetComponent 方法确实开销很大,因此不建议频繁调用它(即每帧多次)。相反,您应该获取它并将结果缓存在其他地方。


因此,要实现这一点,您可以使用标准提供的 typeid 运算符和 std::type_indexstd::type_index 对于每种类型都是唯一的,可以用作映射键(参见 this reference page )。

这是一个示例实现:

#include <typeindex>
#include <map>
#include <cassert>

//Base class of all components
class Component {
public:
virtual ~Component() = default;
Component(const Component& rhs) = delete;
protected:
Component() = default;
};

class Rigidbody : public Component {

};

class MeshRenderer : public Component {

};

class Text : public Component {
public:
std::string text;
};

class GameObject {
private:
std::multimap<std::type_index, Component*> m_components;
public:
template<typename T,
typename = std::enable_if_t<std::is_base_of_v<Component, T>>>
T* add_component() {
return dynamic_cast<T*>(m_components.insert(std::make_pair(std::type_index(typeid(T)), new T))->second);
}

template<typename T,
typename = std::enable_if_t<std::is_base_of_v<Component, T>>>
T* get_component() {
auto it = m_components.find(std::type_index(typeid(T)));
if (it == m_components.end()) return nullptr;
return dynamic_cast<T*>(it->second);
}
};

int main() {
GameObject gm;
gm.add_component<MeshRenderer>();
auto& text = *gm.add_component<Text>();
assert(gm.get_component<MeshRenderer>() != nullptr);
assert(gm.get_component<Rigidbody>() == nullptr);
text.text = "Hello, World!";
std::cout << gm.get_component<Text>()->text << std::endl;
return 0;
}

输出应该是:Hello, World!

关于c++ - 如何改进 GetComponent<> 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57649853/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com