6
我目前正在整合一個實體組件系統,如看到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));
}
這顯然是一個非常幼稚的做法,所以我試圖使各個組件都有自己的互斥。這似乎是合乎邏輯的性能選擇,但是物理結果(通過位置組件查詢)並不總是一致和可靠的。
什麼是實現順利更新過程的最有效方式?我應該讓它一次更新整個世界還是做更多的增量?
編輯:我注意到指針獲取方案有缺陷,但讓我們假設這些指針是有效的。
我應該補充說,當你做同步點時,你想停止你的物理引擎的集成。 – Simon 2010-07-24 22:48:55
我同意。擁有許多同步點可能看起來很有效率,但在繪製場景之前您仍然需要製作一個屏障,從而破壞每個組件鎖定的目的。還要注意,你經常想讓物理運行在與圖形不同的幀率上。我會專注於每個物理更新的一個鎖,並讓遊戲引擎從每個圖形框上最近的物理數據中進行插值。 – 2010-07-27 07:15:59