Actualmente estoy integrando un sistema de componentes de entidad, como se ve en here, con un motor de física y un motor de gráficos. Todo estaba bien hasta hace poco tiempo decidiendo que la física debería funcionar en su propio hilo. (¡Gracias Glenn Fiedler!)¿Cómo puedo hacer que mi subproceso de sistema de entidad componente sea seguro?
Como ahora estoy simplemente bloqueando un mutex compartido por todos los subsistemas al acceder a los componentes.
fragmento del bucle de la física:
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);
}
de fragmentos de bucle de gráficos:
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));
}
Esto es obviamente una implementación muy ingenuo, por lo que intentó hacer los componentes individuales tienen sus propias exclusiones mutuas. Parecía la opción de rendimiento lógico, pero luego los resultados de la física (como se consulta a través del componente de posición) no siempre serían consistentes y confiables.
¿Cuál sería la forma más eficiente de llevar a cabo un proceso de actualización fluido? ¿Debo dejar que actualice todo el mundo de una vez o hacer algo más incremental?
Editar: Me ha llamado la atención que el esquema de adquisición del puntero es defectuoso, pero supongamos que los punteros son válidos.
Debo agregar que desea detener la integración de su motor físico cuando hace los puntos de sincronización. – Simon
Estoy de acuerdo. Tener muchos puntos de sincronización puede parecer eficiente, pero aún tendrá que crear una barrera antes de dibujar la escena, lo que frustra el objetivo de los bloqueos por componente. Tenga en cuenta también que a menudo quiere dejar que la física se ejecute en una velocidad de fotogramas diferente a la de los gráficos. Me centraría en un bloqueo por actualización física y dejaría que el motor del juego se interpusiera a partir de los datos de física recientes en cada cuadro de gráficos. –