2010-07-24 82 views
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)); 
} 

這顯然是一個非常幼稚的做法,所以我試圖使各個組件都有自己的互斥。這似乎是合乎邏輯的性能選擇,但是物理結果(通過位置組件查詢)並不總是一致和可靠的。

什麼是實現順利更新過程的最有效方式?我應該讓它一次更新整個世界還是做更多的增量?

編輯:我注意到指針獲取方案有缺陷,但讓我們假設這些指針是有效的。

回答

2

當涉及到在遊戲引擎中運行的物理引擎時,我建議您在每個幀中有一個同步點,您可以複製這些位置/您可能需要從物理系統到組件系統的任何信息。如果你願意,可以稱它爲dubbel-buffering。你的位置的內部和外部實例(世界矩陣/速度等)。

物理位置上的一幀延遲並不是任何玩家會注意到的。

另一方面,我更喜歡用盡可能多的線程來實現物理引擎,而其餘的遊戲引擎最好什麼也不做。子彈和Havok似乎最適合這種解決方案。

+0

我應該補充說,當你做同步點時,你想停止你的物理引擎的集成。 – Simon 2010-07-24 22:48:55

+2

我同意。擁有許多同步點可能看起來很有效率,但在繪製場景之前您仍然需要製作一個屏障,從而破壞每個組件鎖定的目的。還要注意,你經常想讓物理運行在與圖形不同的幀率上。我會專注於每個物理更新的一個鎖,並讓遊戲引擎從每個圖形框上最近的物理數據中進行插值。 – 2010-07-27 07:15:59