introduzione
I sistemi entità-componente sono una tecnica architettonica orientata agli oggetti.
Non esiste un consenso universale sul significato del termine, lo stesso della programmazione orientata agli oggetti. Tuttavia, è chiaro che i sistemi entità-componente sono specificamente intesi come un'alternativa architettonica all'ereditarietà . Gerarchie di ereditarietà sono naturali per esprimere quello che un oggetto è , ma in certi tipi di software (come i giochi), si preferisce esprimere ciò che un oggetto fa .
È un modello a oggetti diverso da quello di "classi ed ereditarietà" a cui probabilmente sei abituato a lavorare in C ++ o Java. Le entità sono espressive come le classi, proprio come i prototipi come in JavaScript o Self: tutti questi sistemi possono essere implementati l'uno nell'altro.
Esempi
Diciamo di lasciare che Player
sia un soggetto con Position
, Velocity
e KeyboardControlled
componenti, che fanno le cose ovvie.
entity Player:
Position
Velocity
KeyboardControlled
Sappiamo che Position
devono essere influenzati da Velocity
e Velocity
da KeyboardControlled
. La domanda è: come vorremmo modellare quegli effetti.
Entità, componenti e sistemi
Supponiamo che i componenti non abbiano riferimenti reciproci; un Physics
sistema esterno attraversa tutti i Velocity
componenti e aggiorna l' Position
entità corrispondente; un Input
sistema attraversa tutti i KeyboardControlled
componenti e aggiorna il file Velocity
.
Player
+--------------------+
| Position | \
| | Physics
/ | Velocity | /
Input | |
\ | KeyboardControlled |
+--------------------+
Questo soddisfa i criteri:
I sistemi sono ora responsabili della gestione degli eventi e della messa in atto del comportamento descritto dai componenti. Sono anche responsabili della gestione delle interazioni tra entità, come le collisioni.
Entità e componenti
Tuttavia, supponiamo che i componenti che fare hanno riferimenti a uno con l'altro. Ora l'entità è semplicemente un costruttore che crea alcuni componenti, li lega insieme e gestisce le loro vite:
class Player:
construct():
this.p = Position()
this.v = Velocity(this.p)
this.c = KeyboardControlled(this.v)
L'entità potrebbe ora inviare l'input e aggiornare gli eventi direttamente ai suoi componenti. Velocity
risponderebbe agli aggiornamenti e KeyboardControlled
risponderebbe all'input. Questo soddisfa ancora i nostri criteri:
Qui le interazioni tra componenti sono esplicite, non imposte dall'esterno da un sistema. I dati che descrivono un comportamento (qual è la quantità di velocità?) E il codice che lo mette in atto (che cos'è la velocità?) Sono accoppiati, ma in modo naturale. I dati possono essere visualizzati come parametri del comportamento. E alcuni componenti non agiscono affatto: a Position
è il comportamento di trovarsi in un luogo .
Le interazioni possono essere gestite a livello dell'entità ("quando un'entità si Player
scontra con un Enemy
...") o a livello di singoli componenti ("quando un'entità con si Life
scontra con un'entità con Strength
...").
componenti
Qual è il motivo dell'esistenza dell'entità? Se è semplicemente un costruttore, possiamo sostituirlo con una funzione che restituisce un set di componenti. Se in seguito vogliamo interrogare le entità in base al loro tipo, possiamo anche avere un Tag
componente che ci consente di fare proprio questo:
function Player():
t = Tag("Player")
p = Position()
v = Velocity(p)
c = KeyboardControlled(v)
return {t, p, v, c}
Le interazioni ora devono essere gestite da query astratte, disaccoppiando completamente gli eventi dai tipi di entità. Non ci sono più tipi di entità da interrogare: i Tag
dati arbitrari sono probabilmente meglio usati per il debug della logica di gioco.
Conclusione
Le entità non sono funzioni, regole, attori o combinatori di flussi di dati. Sono nomi che modellano fenomeni concreti - in altre parole, sono oggetti. È come dice Wikipedia: i sistemi entità-componente sono un modello di architettura software per la modellazione di oggetti generali.