2010-07-24 9 views
6

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.

Respuesta

2

Cuando se trata de motores físicos que funcionan con motores de juegos, le sugiero que tenga un punto de sincronización una vez por cuadro donde copie las posiciones/información que pueda necesitar del sistema de física en su sistema de componentes. Llámalo dubbel-buffering si lo deseas. Una instancia interna y externa de su posición (matriz/velocidades mundiales, etc.).

Hasta un cuadro de retraso en la física de posiciones no es algo que cualquier jugador se dará cuenta.

En otra nota, prefiero implementar motores de física de una manera que use tantos hilos como sea posible mientras que el resto del motor del juego preferiblemente no hace nada. Bullet y Havok parecen funcionar mejor con esta solución.

+0

Debo agregar que desea detener la integración de su motor físico cuando hace los puntos de sincronización. – Simon

+2

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. –

Cuestiones relacionadas