Registrati Gioco Componenti oggetti in gioco sottosistemi? (Progettazione Gioco di oggetti Component-based)
-
08-10-2019 - |
Domanda
Sto creando un sistema a oggetti di gioco basato su componenti . Alcuni consigli:
-
GameObject
è semplicemente un elenco diComponents
. - Ci sono
GameSubsystems
. Ad esempio, il rendering, la fisica ecc OgniGameSubsystem
contiene puntatori a alcune delleComponents
.GameSubsystem
è un'astrazione molto potente e flessibile:. rappresenta ogni fetta (o un aspetto) del mondo di gioco
V'è la necessità di un meccanismo di registrazione Components
a GameSubsystems
(quando viene creata GameObject
e composto). Ci sono 4 si avvicina :
- 1: catena del modello di responsabilità . Ogni
Component
è offerto ad ogniGameSubsystem
.GameSubsystem
prende una decisione cheComponents
di registrare (e come organizzarle). Ad esempio, può registrare GameSubsystemRender Renderable Componenti.
pro. Components
non sanno nulla di come vengono utilizzati. Accoppiamento basso. A. Siamo in grado di aggiungere nuovi GameSubsystem
. Per esempio, aggiungiamo GameSubsystemTitles che registra tutte ComponentTitle e garantisce che tutti i titoli è unico e fornisce l'interfaccia per quering oggetti per titolo. Naturalmente, ComponentTitle non deve essere riscritto o ereditata in questo caso. B. Siamo in grado di riorganizzare GameSubsystems
esistente. Ad esempio, GameSubsystemAudio, GameSubsystemRender, GameSubsystemParticleEmmiter può essere incorporata in GameSubsystemSpatial (a posto tutto l'audio, emmiter, render Components
nella stessa gerarchia e utilizzare le trasformazioni genitore-relativo).
con. Ogni da ogni controllo. Molto innefficient.
con. Subsystems
sapere su Components
.
- 2:. Ogni ricerche
Subsystem
perComponents
di tipi specifici
pro. prestazioni migliori rispetto a Approach 1
.
con. Subsystems
ancora sapere di Components
.
- 3:
Component
si registri inGameSubsystem(s)
. Sappiamo che a tempo di compilazione che c'è una GameSubsystemRenderer, in modo di lasciare ComponentImageRender chiamerà qualcosa come GameSubsystemRenderer :: registro (ComponentRenderBase *).
Observer modello. sottoscriveComponent
per evento "aggiornamento" (inviato daGameSubsystem(s)
).
pro. Prestazione. Non ci sono controlli inutili come in Approach 1
e Approach 2
.
con. Components
sono mal accoppiato GameSubsystems
.
- 4: mediatore modello.
GameState
(che contieneGameSubsystems
) può implementare registerComponent (Component *).
pro. Components
e al know GameSubystems
nulla gli uni degli altri.
con. In C ++ sarebbe simile typeid-switch brutto e lento.
Domande:
Quale approccio è migliore e per lo più utilizzati nella progettazione basata su componenti? Che Pratica dice? Tutti i suggerimenti circa (data-driven) attuazione di Approach 4
?
Grazie.
Soluzione
Vota il terzo approccio.
Attualmente sto lavorando su un sistema oggetto di gioco basato su componenti e vedo chiaramente alcuni dei vantaggi aggiuntivi di questo approccio:
-
Il componente è sempre più autosufficiente sottoentità in quanto dipende solo su un insieme di sottosistemi disponibili (Presumo che questo set è fissato nel progetto).
-
progettazione dei dati-driven è più applicabile. Idealmente, in questo modo è possibile progettare un sistema in cui i componenti sono completamente definiti in termini di dati, ma non C ++.
EDIT: Una caratteristica ho pensato mentre si lavora su CBGOS. A volte è conveniente avere la capacità di progettare e costruire subsystemless componenti passivi. Quando questo è sulla vostra mente il quarto approccio è l'unico modo.
Altri suggerimenti
Il mio approccio è stato quello di implementare il modello di delega all'interno di ciascun sottosistema. Poiché ogni sottosistema è interessato solo a un sottoinsieme dei componenti totali ogni entità può contenere, i negozi di proxy puntatori ai soli componenti cure sistema merito, ad esempio, un sistema di movimento solo preoccupa per posizione e velocità, quindi ha bisogno di un proxy che memorizza due puntatori, a tali componenti. Se l'entità manca uno o più di questi, allora il sottosistema lo ignorerà. Se entrambi i componenti sono presenti, quindi un nodo proxy viene creato e aggiunto a una raccolta interna. E 'anche utile per il proxy per memorizzare il valore identificatore univoco per l'entità, in modo che possono essere aggiunti proxy / rimosso in tempo costante da ogni sottosistema, nel caso fosse necessario.
In tal modo una, dovrebbe un'entità essere richiesto di essere rimosso dal motore, un singolo messaggio contenente l'ID del soggetto può essere inviato ad ogni sottosistema. La delega può essere rimosso da ogni collezione sottosistema in modo indipendente.