Entidades y componentes

Aprende lo esencial sobre entidades y componentes en una escena de Decentraland

Las escenas de Decentraland se construyen alrededor de entities, components y systemsarrow-up-right. Este es un patrón común utilizado en la arquitectura de varios motores de juego, que permite una fácil composabilidad y escalabilidad.



Visión general

Entities son la unidad básica para construir todo en las escenas de Decentraland. Todos los objetos 3D visibles e invisibles y los reproductores de audio en tu escena serán cada uno una entity. Una entity no es más que un id, que puede ser referenciado por components. La entity en sí no tiene propiedades ni métodos propios, simplemente sirve para agrupar varios components.

Components definen los rasgos de una entity. Por ejemplo, un Transform component almacena las coordenadas, rotación y escala de la entity. Un MeshRenderer component le da a la entity una forma visible (como un cubo o una esfera) cuando se renderiza en la escena, un Material component le da a la entity un color o textura. También puedes crear components personalizados para los datos que requiera tu escena, por ejemplo un health podría almacenar el valor de salud restante de una entity, y añadirlo a entities que representen enemigos no jugadores en un juego.

Si estás familiarizado con el desarrollo web, piensa en las entities como el equivalente a Elements en un DOM tree, y en los components como attributes de esos elementos.

En el Scene Editor in Creator Hubarrow-up-right, puedes ver los components que pertenecen a una entity seleccionándola.


circle-exclamation


Components como Transform, Material o cualquiera de los shape components están estrechamente ligados al renderizado de la escena. Si los valores en estos components cambian, eso por sí solo es suficiente para que el engine cambie cómo se renderiza la escena en el siguiente frame.

El engine es la parte de la escena que se sitúa en el medio y gestiona todas las demás partes. Determina qué entities se renderizan y cómo los jugadores interactúan con ellas. También coordina qué funciones de systemsarrow-up-right se ejecutan y cuándo.

Los components están destinados a almacenar datos sobre su entity referenciada. Solo pueden almacenar estos datos, no pueden modificar estos datos por sí mismos. Todos los cambios en los valores de los components son llevados a cabo por Systemsarrow-up-right. Los Systems están completamente desacoplados de los components y las entities en sí. Las entities y los components son agnósticos respecto a qué systems están actuando sobre ellos.

Sintaxis para entities y components

El ejemplo abajo muestra algunas operaciones básicas para declarar y configurar entities y components básicos.

circle-exclamation

Cuando se crea un component, siempre se asigna a una entity padre. Los valores del component entonces afectan a la entity.

Eliminar entities

Para eliminar una entity del engine, usa engine.removeEntity()

Si una entity eliminada tiene alguna child entities, estas cambian su parent de vuelta a la por defecto engine.RootEntity entity, que está posicionada en la posición base de la escena, con una escala de 1.

Para eliminar una entity y también todos sus children (y cualquier children de sus children, recursivamente), usa la removeEntityWithChildren() helper.

circle-info

💡 Consejo: En lugar de eliminar una entity del engine, en algunos casos puede ser mejor hacerla invisible, en caso de que quieras poder cargarla de nuevo sin ningún retraso. Ver Make invisiblearrow-up-right

Eliminar entities detrás de escena

Una entity es solo un id que es referenciado por sus components. Así que al eliminar una entity en realidad estás eliminando cada uno de los components que referencian esa entity. Esto significa que si eliminas manualmente todos los components de una entity, tendrá el mismo efecto que hacer engine.removeEntity().

Una vez que los components de la entity son eliminados, el id de esa entity queda libre para ser referenciado por nuevos components como una entity completamente nueva.

Entities anidadas

Una entity puede tener otras entities como children. Gracias a esto, podemos organizar entities en árboles, al igual que el HTML de una página web.



Para establecer una entity como parent de otra, la entity child debe tener un Transform component. Entonces puedes establecer el campo parent con una referencia a la entity parent.

Una vez que se asigna un parent, puede leerse desde la child entity desde el campo parent en su Transform component.

Si una entity parent tiene un Transform component que afecta su posición, escala o rotación, sus child entities también se ven afectadas. Cualquier valor de posición o rotación se suma, cualquier valor de escala se multiplica.

Si ni la parent ni la child entity tienen un Transform component, se usan los siguientes valores por defecto.

  • Para position, el centro del parent es 0, 0, 0

  • Para rotation la rotación del parent es el quaternion 0, 0, 0, 1 (equivalente a los ángulos Euler 0, 0, 0)

  • Para scale, el parent se considera que tiene un tamaño de 1. Cualquier cambio de tamaño del parent afecta la escala y posición en proporción.

Entities sin component de shape son invisibles en la escena. Estas pueden usarse como envoltorios para manejar y posicionar múltiples entities como un grupo.

Para separar una child entity de su parent, puedes asignar el parent de la entity a engine.RootEntity.

circle-exclamation

En el Scene Editor, puedes ver toda la jerarquía de entities anidadas en tu escena en el panel lateral izquierdo.



Obtener una entity por ID

Cada entity en tu escena tiene un número único id. Puedes recuperar un component que hace referencia a una entity específica desde el engine basado en este ID.

circle-exclamation

Por ejemplo, si el clic de un jugador o un raycastarrow-up-right impacta una entity, esto devolverá el id de la entity impactada, y puedes usar el comando arriba para obtener el Transform component de la entity que coincida con ese id. También puedes obtener cualquier otro component de esa entity de la misma manera.

Obtener una entity por nombre

Al añadir entities mediante arrastrar y soltar en el Scene Editor, cada entity tiene un nombre único. Usa la engine.getEntityOrNullByName() function para referenciar una de estas entities desde tu código. Pasa el nombre de la entity como una string, tal como aparece en la UI del Scene Editor, en la vista de árbol a la izquierda.

circle-exclamation

Eres libre de realizar cualquier acción sobre una entity obtenida por este método, como añadir o eliminar components, modificar valores de components existentes, o eliminar la entity del engine.

Todas las entities añadidas mediante la UI del Scene Editor tienen un Name component, puedes iterar sobre todas ellas así:

Añadir o reemplazar un component

Cada entity solo puede tener un component de un tipo dado. Por ejemplo, si intentas asignar un Transform a una entity que ya tiene uno, esto causará un error.

Para prevenir este error, puedes usar .createOrReplace en lugar de .create. Este comando sobrescribe cualquier component existente del mismo tipo si existe, de lo contrario crea un component nuevo igual que .create.

circle-exclamation

Acceder a un component desde una entity

Puedes acceder a los components de una entity usando el .get() de la entity o las funciones getMutable() .

La get() function obtiene una referencia de solo lectura al component. No puedes cambiar ningún valor desde esta referencia del component.

Si deseas cambiar los valores del component, usa la getMutable() function en su lugar. Si cambias los valores en la versión mutable del component, estás afectando directamente a la entity a la que pertenece ese component.

Ver mutable dataarrow-up-right para más detalles.

circle-exclamation

El ejemplo anterior modifica directamente el valor de la x escala en el Transform component.

Si no estás totalmente seguro de si la entity tiene el component que intentas obtener, usa getOrNull() o getMutableOrNull().

circle-exclamation

Si el component que intentas obtener no existe en la entity:

  • get() y getMutable() devuelve un error.

  • getOrNull() y getMutableOrNull() devuelve Null.

Eliminar un component de una entity

Para eliminar un component de una entity, usa el deleteFrom() método del tipo de component.

Si intentas eliminar un component que no existe en la entity, esta acción no generará errores.

circle-exclamation

Comprobar si existe un component

Puedes comprobar si una entity posee una instancia de cierto component usando la función has() . Esta función devuelve true si el component está presente, y false si no lo está. Esto puede ser muy útil para usar en la lógica condicional de tu escena.

circle-info

💡 Consejo: También puedes query componentsarrow-up-right para obtener una lista completa de entities que contienen un component específico, o un conjunto específico de components. No iteres manualmente sobre todas las entities de la escena para comprobar cada una con un has() , ese enfoque es mucho menos eficiente.

Comprobar cambios en un component

Usa la onChange function para ejecutar una función de callback cada vez que los valores del component cambian para una entity dada. Esto funciona en cualquier component y es un gran atajo para mantener tu código legible.

La función de callback puede incluir un parámetro de entrada que contiene el nuevo estado del component.

Si el component es eliminado de la entity, entonces la función es llamada con una entrada de undefined.

circle-exclamation

Entities reservadas

Ciertos ids de entity están reservados para entities especiales que existen en cada escena. Pueden ser accedidas mediante los siguientes alias:

  • engine.RootEntity

  • engine.PlayerEntity

  • engine.CameraEntity

circle-exclamation

La entity raíz

Todas las entities en la escena son children de la engine.RootEntity, directa o indirectamente.

Esta entity carece de un Transform component, pero se usa para manejar varios components que representan configuraciones más globales, como skybox controlarrow-up-right, cursor positionarrow-up-right, o screen dimensionsarrow-up-right.

La entity del jugador

La engine.PlayerEntity entity representa el avatar del jugador.

Obtén el Transform component del jugador para obtener la posición y rotación actuales del jugador, ver user dataarrow-up-right. El Transform del jugador es de solo lectura, para modificarlo usa la movePlayerTo() function, learn morearrow-up-right.

También puedes adjuntar objetos al jugador configurándolos como children de esta entity, aunque el Attach to Playerarrow-up-right suele ser la mejor opción para eso.

La entity de la cámara

La engine.CameraEntity entity representa la cámara del jugador.

Obtén el Transform component de la cámara para obtener la posición y rotación de la cámara. El Transform de esta entity también es de solo lectura. Para modificar el ángulo o la posición de la cámara, usa una Virtual cameraarrow-up-right.

También puedes obtener el CameraMode component de la cámara para saber si el jugador está usando el modo de cámara en 1ª o 3ª persona, ver camera modearrow-up-right.

Última actualización