Más diversión con un ES ...
Actualmente, tengo algunos sistemas:
- Renderizador (atributo renderizable, atributo Transformar)
- Movimiento (atributo móvil, atributo de transformación, atributo renderizable [para cuadros delimitadores, etc.])
- Entrada (atributo InputReceiver)
- etc.
Estoy agregando detección de colisión. Lo primero que pensé fue agregar un nuevo sistema que realizara la colisión. Tiene sentido para mí mantener esta aislado del Motion
sistema, ya que no todas las cosas que se mueven o están animadas necesariamente participar en la detección de colisiones - cámaras, niebla, etc - pero parece que Collision
y Motion
son interdependientes.
Cuando Motion
mueve una entidad, la transformación debe validarse Collision
y el movimiento puede cancelarse o ajustarse (rebotar, detenerse en una pared, etc.).
Una alternativa sería crear un atributo Collidable que mantenga una referencia a un objeto de colisión: kd-tree, octree, etc., que se comparte entre entidades que pueden colisionar entre sí. El Motion
sistema sería a continuación, comprobar para ese atributo, y lo utilizan para comprobar o ajustar el movimiento.
Desde la perspectiva del código, esa es una solución aceptable. Sin embargo, desde el punto de vista de la arquitectura ECS, parece que está empujando la lógica al Motion
sistema que no se aplica a todas las entidades que tienen un Movable
atributo.
También podría almacenar un vector de movimiento en el Movable
atributo, y hacer que el Collider
sistema se ajuste Transform
según sea necesario, pero eso implicará duplicar la funcionalidad entre Motion
y Collider
, o una devolución de llamada de Collider
a Motion
con algunos datos sobre la ubicación de la colisión y los datos de superficie para rebote / reflexión, etc. .
Esto puede caer bajo el encabezado de "pirateo de casos especiales", pero me gustaría obtener información de aquellos que han manejado esto antes sin crear una tonelada de código de caso de borde.
La pregunta ¿Cuál es una buena manera de evitar un acoplamiento estrecho entre los sistemas de movimiento y colisión cuando parece que requieren conocimiento mutuo?
Respuestas:
Lo estás pensando demasiado. En mi motor, que también usa un sistema de entidad-componente, cada uno
GameObject
puede tener un puntero a unModuleCollision
.Qué sucede cuando se actualiza el juego:
Update
función para cada unoGameObject
.Update
función, cada unoGameObject
solo actualiza su velocidad y dirección, no su posición.GameObject
carga su posición actual, velocidad y direcciónModuleCollision
, si hay una disponible.ModuleCollision
baseUpdatePost
función en cada unoGameObject
. Si el objeto tiene un módulo de colisión, obtiene la posición, velocidad y dirección actualizadas del módulo de colisión. La posición se actualiza con la velocidad y la dirección.GameObject
construye una matriz final de 3x3 fuera de su posición y rumbo.Sí, hay alguna duplicación de estado, pero está bien. Hacer el manejo de colisiones en una
ModuleCollision
es la mejor manera de hacerlo, porque de lo contrario tendría que verificar cada unaGameObject
para ver si tiene unaModuleCollision
manija.fuente
Lo haría así ...
Tener tres sistemas:
El sistema de movimiento aplica velocidades a las posiciones. El sistema de aceleración aplica fuerzas a las velocidades. El sistema de colisión detecta colisiones y aplica las fuerzas en las direcciones correctas o, si desea colisiones crudas, altera directamente las velocidades.
Por ejemplo, puede calcular el ángulo entre las colisiones usando atan2 , y luego usarlo para aplicar las fuerzas / velocidades correctas a los cuerpos.
Haga que el sistema de detección de colisión transmita mensajes si es necesario también.
fuente