Estoy escribiendo el motor del juego que consta de pocos módulos. Dos de ellos son el motor de gráficos y el motor de física .
Me pregunto si es una buena solución compartir datos entre ellos.
Dos formas (compartir o no) se ven así:
Sin compartir datos
GraphicsModel{
//some common for graphics and physics data like position
//some only graphic data
//like textures and detailed model's verticles that physics doesn't need
};
PhysicsModel{
//some common for graphics and physics data like position
//some only physics data
//usually my physics data contains A LOT more informations than graphics data
}
engine3D->createModel3D(...);
physicsEngine->createModel3D(...);
//connect graphics and physics data
//e.g. update graphics model's position when physics model's position will change
Veo dos problemas principales:
- Una gran cantidad de datos redundantes (como dos posiciones para datos físicos y gráficos)
- Problema con la actualización de datos (tengo que actualizar manualmente los datos gráficos cuando cambian los datos físicos)
Con compartir datos
Model{
//some common for graphics and physics data like position
};
GraphicModel : public Model{
//some only graphics data
//like textures and detailed model's verticles that physics doesn't need
};
PhysicsModel : public Model{
//some only physics data
//usually my physics data contains A LOT more informations than graphics data
}
model = engine3D->createModel3D(...);
physicsEngine->assingModel3D(&model); //will cast to
//PhysicsModel for it's purposes??
//when physics changes anything (like position) in model
//(which it treats like PhysicsModel), the position for graphics data
//will change as well (because it's the same model)
Problemas aquí:
- physicsEngine no puede crear nuevos objetos, simplemente "evaluar" los existentes de engine3D (de alguna manera se ve más anti-independiente para mí)
- Transmitir datos en la función assingModel3D
- physicsEngine y graphicsEngine deben tener cuidado: no pueden eliminar datos cuando no los necesitan (porque el segundo puede necesitarlos). Pero es una situación rara. Además, solo pueden eliminar el puntero, no el objeto. O podemos suponer que graphicsEngine eliminará objetos, physicsEngine simplemente les señalará.
¿Qué camino es mejor?
¿Cuál producirá más problemas en el futuro?
Me gusta más la segunda solución, pero me pregunto por qué la mayoría de los motores de gráficos y física prefieren la primera (¿tal vez porque normalmente solo hacen gráficos o solo motores de física y alguien más los conecta en el juego?).
¿Tienen más pros y contras ocultos?
physics
architecture
graphics
PolGraphic
fuente
fuente
Respuestas:
Hoy en día, más motores de juegos adoptan un diseño de componentes (por ejemplo, Unity, Unreal). En este tipo de diseño, a
GameObject
se compone de una lista de componentes. En su situación, puede haber unMeshComponent
y unPhysicalComponent
, ambos unidos a un solo objeto del juego.Para simplificar, puede poner una variable de transformación del mundo en
GameObject
. Durante la frase de actualización,PhysicalComponent
el mundo se transforma en esa variable. Durante el renderizado,MeshComponent
lee esa variable.La razón detrás de este diseño es desacoplar entre componentes. Ni
MeshComponent
ni sePhysicalComponent
conocen. Solo dependen de una interfaz común. Y puede ser más fácil extender el sistema por composición, que usar una sola jerarquía de herencia.Sin embargo, en un escenario realista, es posible que necesite un manejo más sofisticado entre la sincronización física / gráfica. Por ejemplo, la simulación física puede necesitar ejecutarse en un paso de tiempo fijo (por ejemplo, 30Hz), mientras que la representación debe ser variable. Y es posible que deba interpolar los resultados de la salida del motor de física. Sin embargo, algunos motores de física (por ejemplo, Bullet) tienen soporte directo para este problema.
Unity proporcionó una buena referencia de sus componentes , que vale la pena ver.
fuente
Los motores generalmente eligen la primera opción (malla física propia y malla de renderización propia) porque necesitan datos muy diferentes, tanto en calidad como en cantidad.
Calidad porque al motor de física no le importan las coordenadas de textura, los grupos normales y todo este sofisticado material de render, por ejemplo. Cada uno de ellos espera que los datos en un diseño muy específico se reduzcan a problemas de alineación, empaque, intercalación de datos, etc.
Cantidad porque la malla física generalmente tiene muchos menos triángulos, es una versión simplificada de la malla de renderizado de alta resolución.
Al desacoplar ambos, nos aseguramos de que podamos modificar uno, incluido el cambio de su diseño de datos para un mejor rendimiento, sin dañar el otro. Es mucho más escalable.
fuente
Además de la excelente respuesta de @Millo Yip, me gustaría recordarle que tendrá que compartir los mismos datos con el módulo de Controles y el módulo AI y, si no me equivoco, la mayoría de las bibliotecas de audio tienen una idea de la posición del emisor de sonido. así que también necesitarás compartir los datos con ese módulo.
fuente
Como han dicho otros, es bastante común que la física tenga su estado de datos internos se administra por separado del estado de datos internos del motor de renderizado. A menudo es común ver incluso los datos de transformación (posición / orientación / escala) almacenados por separado de la física y los renderizables porque es posible que exista un objeto de juego que no es impuesto por la física ni se representa, pero requiere una posición mundial para otras mecánicas.
La forma en que los datos pasan de la física a la representación es totalmente suya.
Puede hacerlo a través de algún proceso de despacho entre subsistemas utilizando eventos / mensajes. Puede hacer esto exponiendo una interfaz pública del subsistema de renderizado al subsistema de física para que la física simplemente pueda establecer la posición de un renderizador en particular. Otra opción es que el subsistema renderizable consulta a la entidad para la transformación durante su actualización y realiza la actualización de la posición del componente renderizable, seguido de un dibujo.
Naturalmente, dependiendo de su juego, algunos de estos medios serán más amigables con el caché y tendrán un mejor rendimiento que otros. No me atraparía demasiado de una manera específica en este punto y elegiría un patrón de comunicación y lo probaría. Puede volver a trabajar fácilmente esta parte más adelante para probar varios medios para la optimización.
fuente