【问题标题】:How do I make my component entity system thread safe?如何使我的组件实体系统线程安全?
【发布时间】:2010-07-24 07:31:05
【问题描述】:

我目前正在将一个实体组件系统(如here)与物理引擎和图形引擎集成。这一切都很好,直到最近决定物理应该在自己的线程中运行。 (感谢 Glenn Fiedler!)

现在我只是在访问组件时锁定所有子系统共享的互斥锁。

物理循环的片段:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get physics component from entity
    // This is guaranteed to work ( component must exist for it to present in the map )
    shared_ptr<comp_phys> phys( static_cast<comp_phys*>( it->second->getComponent( COMP_PHYS ).lock().get() ) );
    // Get resulting Box2D vector
    b2Vec2 vec = phys->getBody()->GetPosition();

    // Get position component from entity
    // Same as above, but this is the component shared with the graphics subsystem   
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Update position component from Box2D vector
    pos->setPosition( vec.x, vec.y, 0 );
}

来自图形循环的片段:

lock_guard<mutex> lock( m_EntMutex );
entitymap::iterator it;
for ( it = m_Ents.begin(); it != m_Ents.end(); ++it )
{
    // Get position component from entity
    // This is shared with the physics subsystem
    shared_ptr<comp_pos> pos( static_cast<comp_pos*>( it->second->getComponent( COMP_POS ).lock().get() ) );
    // Get position from position component
    doubleVec3 vec = p->getPosition();

    // Get graphics component from entity
    shared_ptr<comp_gfx> gfx( static_cast<comp_gfx*>( it->second->getComponent( COMP_GFX ).lock().get() ) );
    // Update graphics component from position component
    gfx->getObject()->getParentSceneNode()->setPosition( float(vec.x), float(vec.y), float(vec.z) );
} 

这显然是一个非常幼稚的实现,所以我尝试让各个组件都有自己的互斥锁。这似乎是合乎逻辑的性能选择,但物理结果(通过位置组件查询)并不总是一致和可靠的。

完成平稳更新过程的最有效方式是什么?我应该让它一口气更新整个世界还是做一些更增量的事情?

编辑:我注意到指针获取方案存在缺陷,但让我们假设指针是有效的。

【问题讨论】:

    标签: c++ entity-framework boost multithreading components


    【解决方案1】:

    当涉及在游戏引擎中运行的物理引擎时,我建议您每帧有一个同步点,您可以将位置/您可能需要的任何信息从物理系统复制到组件系统中。如果你愿意,可以称之为 dubbel-buffering。您位置的内部和外部实例(世界矩阵/速度等)。

    物理位置上最多一帧的延迟并不是任何游戏玩家都会注意到的。

    另一方面,我更喜欢以使用尽可能多的线程的方式实现物理引擎,而游戏引擎的其余部分最好什么都不做。 Bullet 和 Havok 似乎最适合这种解决方案。

    【讨论】:

    • 我应该补充一点,您希望在执行同步点时停止物理引擎的集成。
    • 我同意。拥有许多同步点可能看起来很有效,但您仍然需要在绘制场景之前设置屏障,从而违背了每个组件锁定的目的。另请注意,您通常希望让物理运行在与图形不同的帧率上。我会专注于每次物理更新一个锁,并让游戏引擎根据每个图形帧上的最新物理数据进行插值。
    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 2011-05-26
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    相关资源
    最近更新 更多