2010-07-24 6 views
6

Attualmente sto integrando un sistema di componenti di entità, come visto here, con un motore fisico e un motore grafico. Tutto ciò andava bene fino a poco tempo fa, decidendo che la fisica doveva essere in esecuzione nella sua stessa discussione. (Grazie Glenn Fiedler!)Come posso rendere sicuro il thread del sistema di entità componente?

Come ora sto semplicemente bloccando un mutex condiviso da tutti i sottosistemi quando si accede ai componenti.

frammento dal circuito fisica:

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); 
} 

frammento dal ciclo grafici:

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)); 
} 

Questa è ovviamente un'implementazione molto naif, così provai rendendo i singoli componenti hanno le loro mutex. Sembrava la scelta logica delle prestazioni, ma i risultati fisici (come richiesto tramite il componente di posizione) non sarebbero sempre coerenti e affidabili.

Quale sarebbe il modo più efficiente per eseguire un processo di aggiornamento senza problemi? Dovrei lasciarlo aggiornare il mondo intero in una volta sola o fare qualcosa di più incrementale?

Modifica: È venuto a conoscenza che lo schema di acquisizione puntatore è difettoso, ma supponiamo che i puntatori siano validi.

risposta

2

Quando si tratta di motori fisici in esecuzione nei motori di gioco, suggerisco di disporre di un punto di sincronizzazione una volta per fotogramma in cui si copiano le posizioni/qualsiasi informazione che potrebbe essere necessaria dal sistema fisico al sistema componente. Chiamalo per il buffering, se vuoi. Un'istanza interna ed esterna della tua posizione (matrice del mondo/velocità ecc.).

Fino a un frame di ritardo sulle posizioni fisiche non è qualcosa che nessun giocatore noterà.

In un'altra nota, preferisco implementare i motori fisici in un modo che usi il maggior numero di thread possibile mentre il resto del motore di gioco preferisce non fare nulla. Bullet e Havok sembrano funzionare meglio con questa soluzione.

+0

È necessario aggiungere che si desidera interrompere l'integrazione del motore fisico quando si esegue il syncpoint. – Simon

+2

Sono d'accordo. Avere molti punti di sincronizzazione potrebbe sembrare efficiente, ma dovrai comunque creare una barriera prima di disegnare la scena, vanificando lo scopo delle serrature per componente. Si noti inoltre che spesso si desidera far funzionare la fisica su un framerate diverso rispetto alla grafica. Vorrei concentrarmi su un blocco per aggiornamento di fisica e lasciare che il motore di gioco si interpolasse dai dati fisici recenti su ciascun frame grafico. –