2014-08-27 73 views
2

我正在实施一个实体组件系统,并遇到了麻烦,当我试图将一个组件添加到实体。这样做的结构如下:矢量失去引用功能后添加到向量完成

下面将找到一个ID为0的实体,并为其添加一个位置组件。

m_entityManager->addComponentToEntityID(0, ComponentManager::POSITION); 

void EntityManager::addComponentToEntityID(unsigned int entityID, ComponentManager::ComponentType componentType) 
{ 
    std::shared_ptr<Entity> tempEntity; 

    for (unsigned int index = 0; index < m_maximumEntities; ++index) 
    { 
     if (m_entityVector[index].getEntityID() == entityID) 
     { 
      addComponentToEntity(std::make_shared<Entity>(m_entityVector[index]), componentType); 
      break; 
     } 
    } 
} 

以上只是一个辅助功能,首先找到实体,那么它会调用下面的功能:

void EntityManager::addComponentToEntity(std::shared_ptr<Entity> entity, ComponentManager::ComponentType componentType) 
{ 
    if (entity != nullptr) 
    { 
     switch (componentType) 
     { 
      case ComponentManager::POSITION: 
       entity->addComponent(m_componentManager->getUnassignedPositionComponent()); 
       break; 

    default: 
     break; 
     } 
    } 
} 

此功能会发现一个未分配的(免费,可,不加入到实体)定位组件并返回它。

PositionComponent& ComponentManager::getUnassignedPositionComponent() 
{ 
    for (unsigned int index = 0; index < m_positionComponentVector.size(); ++index) 
    { 
     if (m_positionComponentVector[index].isAssigned() == false) 
     { 
      m_positionComponentVector[index].assign(); 
      return m_positionComponentVector[index]; 
     } 
    } 
} 

最后,实体内部,我们有这样的功能:

void Entity::addComponent(Component& component) 
{ 
    m_componentVector.push_back(component); 
} 

实体举行的载体内的EntityManager的内部,在堆栈上正常的对象创建。这与ComponentManager中保存的位置组件相同。

我的目标是保持ComponentManager中的所有组件和系统向ComponentManager发出请求以某种方式处理组件。我想为每个实体保留它所拥有的组件的指针或引用。

我的问题是,一旦Entity :: addComponent()完成后,m_componentVector矢量不再保存添加到它的组件,就像它超出了范围。我认为这个问题是我通过一个副本而不是参考的地方?我最初有参数作为指针,但试图解决它。

+1

你是否试图让'Entity'的'm_componentVector'对'getUnassignedPositionComponent()'返回的组件持有*引用*?您不能将引用存储在容器中。 – 2014-08-27 22:53:03

+0

刚刚它宣布为std :: vector m_componentVector,所以是一个组件实例的向量。 – martingrant 2014-08-27 22:55:27

+2

然后你将一个'Component'拷贝到vector中(如果'PositionComponent'是'Component'的派生类,看起来很可能,那么复制也会切割对象)。 – 2014-08-27 22:56:38

回答

1

相关事实与评论:Entity::m_componentVector被定义为

std::vector<Component> m_componentVector; 

这是存储Component对象,而不是引用一个载体。因此,在Entity::addComponent,线

m_componentVector.push_back(component); 

将使由component引用的对象的副本,并将其添加到所述载体。此副本与从中复制的对象无关。

更糟糕的是,所述component参数addComponent实际引用PositionComponent类型(这大概是从Component衍生)的一个对象。在制作上面提到的副本时,只会复制对应于基类Component的部分。这就是所谓的切片 - 派生类添加的部分只是“切掉”。

您希望使实体的m_componentVector引用存储在ComponentManager中的组件。您不能将引用存储在向量中。您可以存储指针,但如果向向量添加了其他元素(如果存储了指向m_positionComponentVector[0]的指针,并且稍后将更多元素添加到m_positionComponentVector以致需要重新分配,则指向矢量元素的指针可能会失效)你存储的将会失效)。因此,存储索引是您最安全的选择。

+0

感谢您提供丰富的答案。我现在意识到究竟是什么导致了这个问题。您关于使用索引的建议似乎是合理的,我之前曾考虑过这个问题,并且认为通过参考或指针可能会更简单,但您提出的问题肯定会导致一些头痛问题。 我不知道切片,所以很高兴知道。为了推进,我想我会编辑我的代码,使用索引作为引用。 感谢您的协助。 – martingrant 2014-08-27 23:25:57