Devo condividere i dati tra la grafica e il motore fisico nel gioco?


9

Sto scrivendo il motore di gioco composto da pochi moduli. Due di questi sono il motore grafico e il motore fisico .

Mi chiedo se sia una buona soluzione per condividere i dati tra di loro?

Due modi (condivisione o meno) assomigliano a quello:

Senza condividere i dati

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

Vedo due problemi principali:

  1. Molti dati ridondanti (come due posizioni sia per i dati fisici che grafici)
  2. Problema con l'aggiornamento dei dati (devo aggiornare manualmente i dati grafici quando cambiano i dati di fisica)

Con la condivisione di dati

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)

Problemi qui:

  1. physicsEngine non può creare nuovi oggetti, semplicemente "assecondando" quelli esistenti da engine3D (in qualche modo sembra più anti-indipendente per me)
  2. Trasmissione dei dati nella funzione assingModel3D
  3. motore fisico e graficoIl motore deve fare attenzione: non possono cancellare i dati quando non ne hanno bisogno (perché il secondo potrebbe averne bisogno). Ma è una situazione rara. Inoltre, possono semplicemente eliminare il puntatore, non l'oggetto. Oppure possiamo supporre che graphicsEngine eliminerà gli oggetti, PhysicsEngine semplicemente indicandoli.

In che modo è meglio?

Quale produrrà più problemi in futuro?

Mi piace di più la seconda soluzione, ma mi chiedo perché la maggior parte dei motori di grafica e fisica preferisca la prima (forse perché normalmente fanno solo grafica o solo motore di fisica e qualcun altro li collega nel gioco?).

Hanno altri pro e contras nascosti?


Esattamente anche la mia domanda.
danijar,

Risposte:


9

Al giorno d'oggi, più motori di gioco adottano un design di componenti (ad esempio Unity, Unreal). In questo tipo di design, a GameObjectè composto da un elenco di componenti. Nella tua situazione, ci possono essere a MeshComponente a PhysicalComponent, entrambi associati a un singolo oggetto di gioco.

Per semplicità, puoi mettere una variabile di trasformazione del mondo in GameObject. Durante la frase di aggiornamento, gli PhysicalComponentoutput trasformano il mondo in quella variabile. Durante il rendering, MeshComponentlegge quella variabile.

La logica alla base di questo design è di disaccoppiare tra i componenti. Né MeshComponent, né PhysicalComponentsi conoscono. Dipendono solo da un'interfaccia comune. E può essere più semplice estendere il sistema per composizione, piuttosto che usare una singola gerarchia di ereditarietà.

In uno scenario realistico, tuttavia, potrebbe essere necessario un trattamento più sofisticato tra sincronizzazione fisica / grafica. Ad esempio, potrebbe essere necessario eseguire la simulazione fisica in una fase temporale fissa (ad es. 30Hz), mentre il rendering deve essere variabile. E potrebbe essere necessario interpolare i risultati dall'output del motore fisico. Alcuni motori fisici (ad es. Bullet) supportano direttamente questo problema.

Unity ha fornito un buon riferimento ai loro componenti , che vale la pena dare un'occhiata.


Questo non risponde affatto alla domanda, avendo 2 componenti non dice nulla sul fatto che condividano o meno i dati mesh.
Maik Semder,

2
In realtà, offre un design migliore, che è completamente legittimo.
jcora,

7

I motori di solito scelgono la prima opzione (propria mesh fisica e propria mesh di rendering) perché hanno bisogno di dati molto diversi, sia in termini di qualità che di quantità.

Qualità perché il motore fisico non si preoccupa delle coordinate delle trame, dei gruppi normali e di tutte queste fantasiose immagini di rendering, ad esempio. Ognuno di loro si aspetta che i dati in un layout molto specifico si riducano a problemi di allineamento, imballaggio, interfogliatura dei dati ecc.

Quantità perché la mesh fisica di solito ha molti meno triangoli, è una versione semplificata della mesh di rendering ad alta risoluzione.

Disaccoppiando entrambi, ci assicuriamo di poterne modificare uno, compresa la modifica del layout dei dati per prestazioni migliori, senza corrompere l'altro. È molto più scalabile.


0

Oltre alla grande risposta di @Millo Yip, vorrei solo ricordarti che dovrai condividere gli stessi dati con il modulo Controls e il modulo AI e se non sbaglio la maggior parte delle librerie audio ha un'idea della posizione dell'emettitore del suono quindi dovrai condividere i dati anche con quel modulo.


0

Come altri hanno già detto, è abbastanza comune che la fisica abbia il suo stato di dati interno gestito separatamente dallo stato di dati interno del motore di rendering. È spesso comune vedere anche i dati di trasformazione (posizione / orientamento / scala) memorizzati separatamente sia dalla fisica che dai renderizzabili perché è possibile che esista un oggetto di gioco che non è imposto dalla fisica né è reso ma richiede una posizione mondiale per altri meccanici.

Il modo in cui i dati passano dalla fisica al renderizzabile dipende interamente da te.

È possibile farlo tramite un processo di invio tra sottosistemi utilizzando eventi / messaggi. È possibile farlo esponendo un'interfaccia pubblica del sottosistema di rendering al sottosistema di fisica in modo che la fisica possa semplicemente impostare la posizione di un renderizzabile in modo particolare. Un'altra opzione è che il sottosistema renderizzabile interroga l'entità per la trasformazione durante il suo aggiornamento e fa l'aggiornamento della posizione del componente renderizzabile, quindi seguito dal disegno.

Naturalmente, a seconda del tuo gioco, alcuni di questi mezzi saranno più compatibili con la cache e avranno prestazioni migliori rispetto ad altri. A questo punto non mi farei prendere troppo da un modo specifico e scegliere un modello di comunicazione e provarlo. Puoi facilmente rielaborare questa parte in seguito per testare vari mezzi per l'ottimizzazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.