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.
È necessario aggiungere che si desidera interrompere l'integrazione del motore fisico quando si esegue il syncpoint. – Simon
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. –