gpt4 book ai didi

c++ - 在 Entity-Component-System 中拆分组件需要太多的重构

转载 作者:可可西里 更新时间:2023-11-01 18:36:30 26 4
gpt4 key购买 nike

我有一个使用实体组件系统 (ECS) 的现有工作 C++ 游戏库。

我的库的用户想要创建一些组件,例如Cat :-

class Cat{ public:
int hp;
float flyPower;
};

他可以修改hp每个 cat通过例如:-

for(SmartComponentPtr<Cat> cat : getAll<Cat>()){
cat->hp-=5; //#1
}

几天后,他想 split CatHPFlyable :-

class HP{ public:
int hp;
};
class Flyable{ public:
float flyPower;
};

因此,每个 cat该访问 hp将编译错误(例如上面代码中的 #1)。

要解决,用户可以将他的代码重构为:-

for(MyTuple<HP,Flyable> catTuple : getAllTuple<HP,Flyable>()){
SmartComponentPtr<HP> hpPtr=catTuple ; //<-- some magic casting
hpPtr->hp-=5;
}

它有效,但需要在用户代码中进行大量重构(调用 cat->hp 的各个地方)。

ECS拆分组件时如何修改框架/引擎解决可维护性问题?

我从未发现任何方法不受此问题的影响,例如:-

赏金原因

Yuri 的回答是一项很酷的技术,但它仍然需要一些重构。

我当前的糟糕解决方案 (pimpl)

如果我想创建Cat ,我将创建 6 个组件:-

  • Hp_ , Hp_OO
  • Flyable_ , Flyable_OO
  • Cat_ , Cat_OO

这是一个代码示例:-

class Hp_ : public BaseComponent{
int hp=0;
};
class Hp_OO : public virtual BaseComponent{
Hp_* hpPimpl;
public: void damage(float dmg){ hpPimpl->hp-=dmg;}
};
class Flyable_ : public BaseComponent{ public:
float flyPower;
};
class Flyable_OO: public virtual BaseComponent{
Flyable_* flyPimpl;
//other function
};
class Cat_: public virtual BaseComponent{};
class Cat_OO: public virtual Hp_OO , public virtual Flyable_OO{
Cat_* catPimpl;
};

现在,调用是有效的:-

SmartComponentPtr<Cat_OO> catPtr;
catPtr->damage(5); //: so convenient - no need to refactor

实现:-

  1. 如果用户添加 Cat_OO对于实体,我的游戏引擎会自动将其父类添加到实体,例如Hp_ , Hp_OO , Flyable_ , Flyable_OO , 和 Cat_ .
  2. 还必须分配正确的 pimpl 指针/句柄。

  3. ^ 两个 Action 都可以使用回调。

缺点是:-

  • 需要创建很多组件。 (浪费内存)
  • 如果有一个共同的基类,例如BaseComponent ,我需要虚拟继承。 (浪费大量内存)

优点是:-

  • 如果用户查询getAll<Hp_OO>() , Hp_OO每个 Cat_OO也将在返回列表中。
  • 无需重构。

最佳答案

救援的成员指针:

#include <tuple>

template <typename... Components>
struct MultiComponentPtr {
explicit MultiComponentPtr(Components*... components)
: components_{components...}
{}

template <typename Component, typename Type>
Type& operator->*(Type Component::* member_ptr) const {
return std::get<Component*>(components_)->*member_ptr;
}

private:
std::tuple<Components*...> components_;
};

struct Cat {
int hp;
float flyPower;
};

struct HP {
int hp;
};

struct Flyable {
float flyPower;
};

int main() {
{
Cat cat;
MultiComponentPtr<Cat> ptr(&cat);
ptr->*&Cat::hp += 1;
ptr->*&Cat::flyPower += 1;
}

{
HP hp;
Flyable flyable;
MultiComponentPtr<HP, Flyable> ptr(&hp, &flyable);
ptr->*&HP::hp += 1;
ptr->*&Flyable::flyPower += 1;
}
}

从技术上讲,您仍然需要重构,但是将 &Cat::hp 自动替换为 &HP::hp 等是微不足道的

关于c++ - 在 Entity-Component-System 中拆分组件需要太多的重构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56846715/

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