ECS由三个部分构成:
Entity:实体、个体。由多个component组成
Component:组件、数据。由数据组成
System:系统。由逻辑组成
Component:
组件Component是一个基类,有几百个子类,每个子类都有System执行Behavior时所需的成员变量。这里的多态是用来重写Create,以及使用虚析构函数管理声明周期,帮助回收垃圾。另外可能有访问内部状态的helper函数,除此之外Component不应该有Behavior。
class Component{
virtual void Create(resource* m_resource);
virtual ~Component();
}
Entity:
一个Entity其实像是一个对象,可以代表游戏世界中的任意对象,而其内部包含了若干个Component,拥有全局唯一的EntityID,用于标识Entity本身,ID是一个32位无符号整数。
class Entity{
unsigned int ID;
vector<Component> components;
}
System
而System则是系统,是行为,用来制定游戏规则。System本身没有数据,只有方法。在应用中,System之间不可以直接通信,并且一个System只关心某一个固定的Component组合,这个组合称为tuple。
**使用一个System的条件:**System会遍历所有Entity,若Entity当中,拥有System中tuple指定的所有Component,则对该Entity进行处理。
System本身并不关心Entity是谁,它只关心Entity中包含的component。
本人猜想的System和tuple的例子:
class System{
public:
virtual void update(f32 timeStep)=0;
virtual ~System();
}
class HitSystem:public System{
vector<Component> tuple;
public:
virtual void update(f32 timeStep){//其实这段代码干了什么我真不清楚
for(DerpComponent* d:ComponentItr<DerpComponent>(m_admin)){
d->m_timeAccu+=timeStep;
if(d->m_timeAccu>d->m_timeToHerp) this->HerpYourDerp(d,d->Sibling<HerpComponent>());
}
}
for(Entity &entity:world.entitys)
{
if(/*entity中有tuple中的所有component*/)
{//对应处理:
}
}
}
}
实际上的System和tuple的例子:
//tuple
struct PhysicsTuple
{
DynamicPhysicsComponent* m_dynamicPhysics;
TransformComponent* m_transform;
ContactListComponent* m_contacts;
}
//system
void PhysicsSystem::Tick(f32 timeStep)
{
IPhysicWorld* pw=GetPhysicsWorld();
pw->Update(timestep);
//write transeforms of dynamic physics objects
for(PhysicsTuple& t:getPhysicsTuples())
{
IPhysicsProxy* proxy=pw->GetProxy(t.m_dynamicPhysics->m_proxy);
CopyTransform(t.m_transform,proxy);
CopyContacts(t.m_contacts,proxy);
}
}
但是这里我有一点疑问,每一次行为如果需要遍历所有的Entity,那么其复杂度就是tuple的component个数乘以Entity个数乘以Entity内component的个数,这个复杂度会不会很大?
World
(图来自视频截图)
World即是图中的EntityAdmin,其中包含了所有System,用哈希表存的Entity,以及所有Component。 而World里面有Update函数。
void EntityAdmin::Update(f32 timeStep)
{
for(System* s:m_systems) s->Update(timeStep);
}