Ho progettato un sistema di entità per un FPS. In pratica funziona così:
Abbiamo un oggetto "mondo", chiamato GameWorld. Questo contiene una matrice di GameObject, nonché una matrice di ComponentManager.
GameObject contiene un array di componenti. Fornisce anche un meccanismo di eventi che è davvero semplice. I componenti stessi possono inviare un evento all'entità, che viene trasmesso a tutti i componenti.
Component è fondamentalmente qualcosa che dà a GameObject determinate proprietà, e dal momento che GameObject è in realtà solo un contenitore di essi, tutto ciò che ha a che fare con un oggetto di gioco accade nei Componenti. Gli esempi includono ViewComponent, PhysicsComponent e LogicComponent. Se è necessaria la comunicazione tra di loro, ciò può essere fatto attraverso l'uso di eventi.
ComponentManager è solo un'interfaccia come Component e, per ogni classe Component, in genere dovrebbe esserci una classe ComponentManager. Questi gestori di componenti sono responsabili della creazione e dell'inizializzazione dei componenti con proprietà lette da qualcosa come un file XML.
ComponentManager si occupa anche degli aggiornamenti di massa dei componenti, come PhysicsComponent, dove userò una libreria esterna (che fa tutto in una volta).
Per la configurabilità, userò una fabbrica per le entità che leggerà un file XML o uno script, creerò i componenti specificati nel file (che aggiunge anche un riferimento ad esso nel giusto gestore componenti per gli aggiornamenti di massa) e quindi iniettarli in un oggetto GameObject.
Ora arriva il mio problema: proverò a usarlo per i giochi multiplayer. Non ho idea di come affrontare questo.
Primo: quali entità dovrebbero avere i clienti sin dall'inizio? Dovrei iniziare spiegando come un motore a giocatore singolo determinerebbe quali entità creare.
Nell'editor di livello è possibile creare "pennelli" ed "entità". Le spazzole sono per cose come pareti, pavimenti e soffitti, sostanzialmente forme semplici. Le entità sono l'oggetto del gioco di cui ti ho parlato. Quando si creano entità nell'editor di livello, è possibile specificare le proprietà per ciascuno dei suoi componenti. Queste proprietà vengono passate direttamente a qualcosa come un costruttore nello script dell'entità.
Quando si salva il livello per il caricamento del motore, questo viene scomposto in un elenco di entità e delle proprietà associate. I pennelli vengono convertiti in un'entità "worldspawn".
Quando carichi quel livello, istanzia tutte le entità. Sembra semplice, eh?
Ora, per il collegamento in rete delle entità ho riscontrato numerosi problemi. Innanzitutto, quali entità dovrebbero esistere sul client dall'inizio? Supponendo che sia il server che il client dispongano del file di livello, il client potrebbe anche istanziare tutte le entità nel livello, anche se sono presenti solo ai fini delle regole di gioco sul server.
Un'altra possibilità è che il client installi un'entità non appena il server invia informazioni su di essa e ciò significa che il client avrà solo entità di cui ha bisogno.
Un altro problema è come inviare le informazioni. Penso che il server potrebbe usare la delta-compressione, il che significa che invia nuove informazioni solo quando qualcosa cambia, piuttosto che inviare un'istantanea al client in ogni frame. Ciò significa che il server deve tenere traccia di ciò che ogni client conosce al momento.
E infine, come dovrebbe essere iniettata la rete nel motore? Sto pensando a un componente, NetworkComponent, che viene iniettato in ogni entità che dovrebbe essere collegata in rete. Ma come dovrebbe il componente di rete sapere quali variabili mettere in rete, come accedervi e infine come il componente di rete corrispondente sul client dovrebbe sapere come modificare le variabili di rete?
Sto avendo enormi problemi ad avvicinarmi a questo. Ti sarei davvero grato se mi avessi aiutato lungo la strada. Sono aperto a suggerimenti su come migliorare anche la progettazione del sistema dei componenti, quindi non abbiate paura di suggerirlo.