Introducción
Los sistemas de entidad-componente son una técnica arquitectónica orientada a objetos.
No existe un consenso universal de lo que significa el término, igual que la programación orientada a objetos. Sin embargo, está claro que los sistemas de entidad-componente están destinados específicamente como una alternativa arquitectónica a la herencia . Jerarquías de herencia son naturales para expresar lo que un objeto es , pero en ciertos tipos de software (como los juegos), que en lugar expresarían lo que un objeto hace .
Es un modelo de objeto diferente al de "clases y herencia", al que probablemente esté acostumbrado a trabajar en C ++ o Java. Las entidades son tan expresivas como las clases, al igual que los prototipos como en JavaScript o Self: todos estos sistemas se pueden implementar en términos unos de otros.
Ejemplos
Vamos a decir que Player
es una entidad con Position
, Velocity
y KeyboardControlled
componentes, que hacen las cosas obvias.
entity Player:
Position
Velocity
KeyboardControlled
Sabemos que Position
debe verse afectado por Velocity
y Velocity
por KeyboardControlled
. La pregunta es cómo nos gustaría modelar esos efectos.
Entidades, Componentes y Sistemas
Supongamos que los componentes no tienen referencias entre sí; un Physics
sistema externo atraviesa todos los Velocity
componentes y actualiza los Position
de la entidad correspondiente; un Input
sistema atraviesa todos los KeyboardControlled
componentes y actualiza el Velocity
.
Player
+--------------------+
| Position | \
| | Physics
/ | Velocity | /
Input | |
\ | KeyboardControlled |
+--------------------+
Esto satisface los criterios:
Los sistemas ahora son responsables de manejar eventos y promulgar el comportamiento descrito por los componentes. También son responsables de manejar las interacciones entre entidades, como las colisiones.
Entidades y Componentes
Sin embargo, supongamos que los componentes de hacerlo tienen referencias a los otros. Ahora la entidad es simplemente un constructor que crea algunos componentes, los une y gestiona sus vidas:
class Player:
construct():
this.p = Position()
this.v = Velocity(this.p)
this.c = KeyboardControlled(this.v)
La entidad ahora puede enviar eventos de entrada y actualización directamente a sus componentes. Velocity
respondería a las actualizaciones y KeyboardControlled
respondería a las entradas. Esto aún satisface nuestros criterios:
Aquí las interacciones de los componentes son explícitas, no impuestas desde el exterior por un sistema. Los datos que describen un comportamiento (¿cuál es la cantidad de velocidad?) Y el código que lo promulga (¿qué es la velocidad?) Están acoplados, pero de manera natural. Los datos se pueden ver como parámetros para el comportamiento. Y algunos componentes no actúan en absoluto: a Position
es el comportamiento de estar en un lugar .
Las interacciones pueden manejarse a nivel de la entidad ("cuando una Player
colisión con un Enemy
...") o al nivel de componentes individuales ("cuando una entidad con una Life
colisión con una entidad con Strength
...").
Componentes
¿Cuál es la razón por la cual la entidad existe? Si es simplemente un constructor, entonces podemos reemplazarlo con una función que devuelve un conjunto de componentes. Si luego queremos consultar entidades por su tipo, también podemos tener un Tag
componente que nos permita hacer exactamente eso:
function Player():
t = Tag("Player")
p = Position()
v = Velocity(p)
c = KeyboardControlled(v)
return {t, p, v, c}
Las interacciones ahora deben ser manejadas por consultas abstractas, desacoplando completamente los eventos de los tipos de entidad. No hay más tipos de entidades para consultar: los Tag
datos arbitrarios probablemente se usan mejor para la depuración que la lógica del juego.
Conclusión
Las entidades no son funciones, reglas, actores o combinadores de flujo de datos. Son sustantivos que modelan fenómenos concretos; en otras palabras, son objetos. Es como dice Wikipedia: los sistemas de entidad-componente son un patrón de arquitectura de software para modelar objetos generales.