2010-10-18 18 views
7

Estoy creando un component-based game object system. Algunos consejos:¿Registrar componentes de objetos de juego en los subsistemas del juego? (Diseño de objeto de juego basado en componentes)

  1. GameObject es simplemente una lista de Components.
  2. Hay GameSubsystems. Por ejemplo, renderizado, física, etc. Cada GameSubsystem contiene punteros a algunos de Components. GameSubsystem es una abstracción muy poderosa y flexible: representa cualquier sector (o aspecto) del mundo del juego.

Hay una necesidad de un mecanismo de registro de Components en GameSubsystems (cuando se crea y compuesto GameObject). Hay 4 se aproxima:


  • 1: Chain of responsibility patrón. Cada Component se ofrece a cada GameSubsystem. GameSubsystem toma una decisión que Components para registrarse (y cómo organizarlos). Por ejemplo, GameSubsystemRender puede registrar componentes de Renderable.

pro. Components no saben nada sobre cómo se usan. Bajo acoplamiento A. Podemos agregar el nuevo GameSubsystem. Por ejemplo, agreguemos GameSubsystemTitles que registre todos los ComponentTitle y garantice que cada título sea único y proporcione una interfaz para buscar objetos por título. Por supuesto, ComponentTitle no se debe reescribir o heredar en este caso. B. Podemos reorganizar el existente GameSubsystems. Por ejemplo, GameSubsystemAudio, GameSubsystemRender, GameSubsystemParticleEmmiter se pueden fusionar en GameSubsystemSpatial (para colocar todo el audio, emmiter, renderizar Components en la misma jerarquía y usar transformaciones relativas a los padres).

con. Control de todos los días. Muy ineficiente.

con. Subsystems saber Components.


  • 2: Cada Subsystem búsquedas de Components de tipos específicos.

pro. Mejor rendimiento que en Approach 1.

con. Subsystems todavía saben sobre Components.


  • 3: Component registra a sí mismo en GameSubsystem(s). Sabemos en tiempo de compilación que hay GameSubsystemRenderer, así que vamos a ComponentImageRender a llamar a algo como GameSubsystemRenderer :: register (ComponentRenderBase *).
    Observer patrón. Component se suscribe al evento "actualizar" (enviado por GameSubsystem(s)).

pro. Actuación.Sin controles innecesarios como en Approach 1 y Approach 2.

con. Components están mal acoplados con GameSubsystems.


  • 4: Mediator patrón. GameState (que contiene GameSubsystems) puede implementar registerComponent (Component *).

pro. Components y GameSubystems no saben nada el uno del otro.

con. En C++ se vería como un interruptor de tipo de letra feo y lento.


Preguntas: qué método es mejor y sobre todo utilizada en el diseño basado en componentes? ¿Qué práctica dice? ¿Alguna sugerencia sobre la implementación (basada en datos) de Approach 4?

Gracias.

Respuesta

2

Vote por el tercer enfoque.

Actualmente estoy trabajando en el sistema de juego de objetos basado en componentes y veo claramente algunas de las ventajas adicionales de este enfoque:

  • el componente es cada vez más subentidad basta a sí mismo, ya que sólo depende de una conjunto de subsistemas disponibles (supongo que este conjunto está fijo en su proyecto).

  • El diseño basado en datos es más aplicable. Idealmente, de esta manera usted puede diseñar un sistema donde los componentes estén completamente definidos en términos de datos pero no en C++.


EDIT: Una característica pensaba mientras se trabaja en CBGOS. A veces es conveniente tener la capacidad de diseñar y construir subsistemless componentes pasivos. Cuando esto está en su mente, el cuarto enfoque es la única forma.

+0

Estoy de acuerdo con usted en que estas ventajas son muy valiosas. Pero el primero tiene otro lado: no hay reutilización de 'Componente' entre proyectos (con diferentes conjuntos de' Subsistemas').La recomposición de subsistemas en un solo proyecto se convierte en un problema, también. Puede haber cientos de 'Componentes', reescribirlos a todos es una tarea tediosa. Creo que esa segunda ventaja se puede alcanzar en otros enfoques, también. –

+0

Estoy de acuerdo con tu punto. En un momento me presentaron el diseño CBGOS no tanto como quisiera. Pero el trabajo que encontré para hacer frente a esto me llevó a las siguientes consideraciones: * 1. * Diseñar las interfaces del subsistema de la manera más abstracta para que el conjunto de subsistemas cambie ligeramente en los diferentes proyectos. * 2. * Prefiere la interacción por mensaje entre componentes por encima de todo y corta las dependencias de interfaz donde sea posible. – Keynslug

+0

Puede funcionar. Conocí gente en los foros de gamedev.net que también usan este enfoque. –

1

Mi enfoque fue implementar el patrón de proxy dentro de cada subsistema. Como cada subsistema solo está interesado en un subconjunto de los componentes totales que cada entidad puede contener, el proxy almacena punteros únicamente a los componentes que le interesan, por ejemplo, un sistema de movimiento solo se preocupa por la posición y la velocidad, por lo que necesita un proxy que almacene dos punteros, a esos componentes. Si a la entidad le falta uno o más de ellos, el subsistema la ignorará. Si ambos componentes están presentes, se crea un nodo proxy y se agrega a una colección interna. También es útil que el proxy almacene el valor de identificador único para la entidad, de modo que los proxies se puedan agregar/eliminar en tiempo constante de cada subsistema, si fuera necesario.

De esta forma, si se requiere que una entidad sea eliminada del motor, se puede enviar un mensaje único que contenga la identificación de la entidad a cada subsistema. El proxy se puede eliminar de cada colección de subsistema de forma independiente.

+0

Buen enfoque, Ian. –

Cuestiones relacionadas