Estoy trabajando en un juego con una arquitectura basada en componentes. Un Entity
posee un conjunto de Component
instancias, cada una de las cuales tiene un conjunto de Slot
instancias para almacenar, enviar y recibir valores. Funciones de fábrica tales como Player
producir entidades con los componentes necesarios y las conexiones de ranura.
Estoy tratando de determinar el mejor nivel de granularidad para los componentes. Por ejemplo, en este momento Position
, Velocity
y Acceleration
todos son componentes separados, conectados en serie. Velocity
y Acceleration
podría reescribirse fácilmente en un Delta
componente uniforme , o Position
, Velocity
y Acceleration
podría combinarse junto con componentes como Friction
y Gravity
en un Physics
componente monolítico .
¿Debe un componente tener la menor responsabilidad posible (a costa de mucha interconectividad) o los componentes relacionados deben combinarse en monolíticos (a costa de la flexibilidad)? Me estoy inclinando hacia la primera, pero podría usar una segunda opinión.
fuente
Respuestas:
Hay una línea entre la granularidad completa, que no genera desperdicio de código o un estado similar a un blob (razón por la cual se favorecen las arquitecturas de componentes) y la usabilidad.
Obviamente, las cosas pueden tener un
Position
, pero no son necesariamente dinámicas (entonces, ¿por qué tenerVelocity
yAcceleration
?). Sin embargo, algo con unVelocity
va a ser un objeto en movimiento, por lo que tiene sentido también haberAcceleration
agrupado.¿Vas a tener un caso donde v y una va a ser necesaria, pero no desea una simulación física para ellos? Del mismo modo, ¿habrá algún punto
Gravity
si no son objetos de física?tl; dr Agrupe lo que tiene sentido.
fuente
Entity
tienePosition
algunos componentes que hacen quePosition
participen en la física, entoncesEntity
es de facto físico. Creo que lo que puedo hacer es agregar algunos componentes para la agrupación lógica y mantener todos los componentes fundamentales en una sola responsabilidad. Por lo que añadir, por ejemplo, unaMovable
a unaEntity
tendría el mismo efecto que la adición de unaPosition
,Velocity
yAcceleration
.Para evitar la microgestión de todas y cada una de las variables que sugeriría al comenzar con fuerza, elija divisiones en torno a la responsabilidad y refactorice cuando la situación se presente de forma lógica. Puede comenzar los primeros diseños en papel. En algún momento, estas divisiones groseras de responsabilidad se convertirán en los componentes básicos de sus entidades.
Entonces, para un ejemplo apresurado, tienes Game. El juego se divide en Medio Ambiente + Estado. El entorno se divide en StaticWorld + MovingStuff. El estado se divide en AIControlled + PlayerControlled. La idea general de Daño se divide en TakesDamage + GivesDamage.
Y así.
Muy parecido al consejo común de "¡Crea juegos, no motores!" para los nuevos practicantes recomiendo "¡Crear juegos, no sistemas de componentes elaborados!" porque solo con experiencia personal con un juego en ejecución sabrás si se requiere un complejo sistema de componentes en futuros trabajos.
fuente
Mi conjetura sería combinar componentes que tendrán mucha interacción. En su caso, mantendría la posición en un solo componente y mantendría la velocidad y la aceleración juntas en un componente de física.
Pero depende mucho de las características de su juego (a menos que esté creando un marco sin un juego específico en mente).
fuente
Me doy cuenta de que esta es una vieja pregunta, pero tal vez alguien encuentre útil esta respuesta.
Creo que eso
Systems
lo ayudará mejor a comprender cómo construir Componentes. Los sistemas existen en arquitecturas donde los componentes no contienen su propia lógica, aparte de simples getter / setters y funciones auxiliares. Los sistemas operan en entidades que satisfacen los requisitos de los componentes. Esta es la razón por la cual es mejor separar los datos de los componentes tanto como tenga sentido que esos datos se procesen sin los otros datos.Por ejemplo, puede tener una
MovementSystem
que actualice sus Entidades enPosition
función de susVelocity
. Esto podría ser para entidades simples en el juego. Pero, para el Jugador y los Enemigos, es posible que desee un movimiento queAcceleration
se proceseAcceleratedMovementSystem
. Pero para Obstáculos puede que quierasFriction
. El terreno también puede tener fricción, pero no tendrá un componente de velocidad. ¿Pero que pasaGravity
? Simplemente agréguelo Player, Enemy y Obstacle, y cree unGravitySystem
para procesarlo.La conclusión es que cuanto más desacoplado su
Components
son, más extensible laEntities
habrá cuando se utilizaSystems
.Editar: hizo la última declaración más clara.
Editar: Ok, he estado trabajando en mi propio sistema y llegué a esta conclusión. Un ejemplo para dividir la posición y la velocidad es que manipular la velocidad hace que la posición cambie con un sistema de movimiento. Como resultado, un 'InputMovementSystem' no necesita una posición para hacer que el jugador se mueva de la entrada del usuario porque el sistema de movimiento recogerá los cambios en la velocidad para aplicar a la posición. De acuerdo, todavía funcionaría bien unirlos, pero ese es un ejemplo de por qué no es necesario que lo sean.
Hace poco leí una publicación de blog que decía algo como esto:
fuente