Entities & Components
Aprende lo esencial sobre entities y components en una escena de Decentraland
Las escenas de Decentraland se construyen en torno a entities, components y systems. Este es un patrón común usado en la arquitectura de varios motores de juego, que permite una fácil componibilidad y escalabilidad.

Descripción general
Entities son la unidad básica para construirlo todo en las escenas de Decentraland. Todos los objetos 3D visibles e invisibles y los reproductores de audio de tu scene serán, cada uno, una entity. Una entity no es más que un id, al que pueden hacer referencia los components. La entity en sí no tiene propiedades ni métodos propios; simplemente sirve para agrupar varios components.
Components definen las características 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 scene; un Material component le da a la entity un color o una textura. También puedes crear custom components para servir con los datos que requiere tu scene, por ejemplo un custom 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 de Elements en un DOM tree, y en los components como attributes de esos elements.
En el Scene Editor in Creator Hub, puedes ver los components que pertenecen a una entity seleccionándola.

📔 Nota: En versiones anteriores del SDK, Entities eran objects que se instanciaban, y podían ampliarse para añadir functions. Desde la versión 7.0 del SDK, las entities son solo un ID. Esta estructura se ajusta mejor a los principios de data oriented programming y puede ayudar al rendimiento de la scene.

Components como Transform, Material o cualquiera de los shape components están estrechamente ligados a la renderización de la scene. Si los valores de estos components cambian, eso basta para que el engine cambie cómo se renderiza la scene en el siguiente frame.
El engine es la parte de la scene que se sitúa en el centro y gestiona todas las demás partes. Determina qué entities se renderizan y cómo interactúan los players con ellas. También coordina qué functions de systems se ejecutan y cuándo.
Los components están pensados para 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 los llevan a cabo los Systems. Los Systems están completamente desacoplados de los components y de las entities en sí. Entities y components son agnósticos a qué systems actúan sobre ellos.
Sintaxis para entities y components
El ejemplo siguiente muestra algunas operaciones básicas para declarar y configurar entities y components básicas.
📔 Nota: En versiones anteriores del SDK, era necesario añadir manualmente una entity al engine para empezar a renderizarla. Desde la versión 7 del SDK, las entities se añaden implícitamente al engine en cuanto se les asigna un component.
Cuando se crea un component, siempre se asigna a una entity padre. Los valores del component luego afectan a la entity.
Eliminar entities
Para eliminar una entity del engine, usa engine.removeEntity(). Esta función devuelve un booleano: true si la entity se eliminó, false si se rechazó la eliminación.
Si una entity eliminada tiene any child entities, estas cambian su parent de vuelta al entity predeterminado, engine.RootEntity que se posiciona en la base de la scene, con una escala de 1.
Entities reservadas por el renderer
Algunos ids de entity están reservados por el renderer para los avatares de jugadores remotos. No puedes eliminar estas entities. Si llamas a engine.removeEntity() en una entity reservada por el renderer, devuelve false y deja todos los components intactos.
El entities reservadas con nombre (engine.RootEntity, engine.PlayerEntity, engine.CameraEntity) son un caso especial: engine.removeEntity() sigue devolviendo false para estas (sus ids nunca se liberan), pero sus components son eliminados. Esto significa que puedes limpiar tus propios components de ellas (por ejemplo, eliminando un InputModifier de engine.PlayerEntity), aunque el id de la entity en sí nunca se libera.
Puedes comprobar el valor de retorno al eliminar entities para manejar casos límite:
Eliminar una entity con sus children
Para eliminar una entity y también todos sus children (y los children de sus children, de forma recursiva), usa el helper removeEntityWithChildren() .
Nota: Si una entity reservada por el renderer está en cualquier parte del tree, removeEntityWithChildren elimina todos los demás descendientes pero deja la entity reservada en su lugar. El Transform.parent de la entity reservada apuntará a una entity eliminada. Esto solo ocurre si tu scene pone una entity reservada como hija de una entity de la scene, lo cual es poco común.
Eliminar entities detrás de escena
Una entity es solo un id referenciado por sus components. Así que al eliminar una entity en realidad estás eliminando cada uno de los components que referencian esta entity. Si eliminas manualmente todos los components de una entity, para el player se verá igual que hacer engine.removeEntity(). Sin embargo, engine.removeEntity() también realiza un poco de contabilidad interna adicional, marcando el id de entity como ya no en uso, por lo que siempre es la forma recomendada de eliminar una entity.
Entities anidadas
Una entity puede tener otras entities como children. Gracias a esto, podemos organizar entities en trees, igual que el HTML de una página web.

Para establecer una entity como parent de otra, la entity hija debe tener un Transform component Transform. Entonces puedes establecer el parent field con una referencia a la entity padre.
Una vez asignado un parent, este puede leerse desde la entity hija mediante el parent field de su Transform component.
Si una entity padre tiene un Transform component que afecta a su posición, escala o rotación, sus entities hijas también se ven afectadas. Los valores de posición o rotación se suman, y los valores de escala se multiplican.
Si la entity padre o hija no tiene un Transform component, se usan los siguientes valores predeterminados.
Para position, el centro del padre es 0, 0, 0
Para rotation la rotación del padre es el quaternion 0, 0, 0, 1 (equivalente a los ángulos de Euler 0, 0, 0)
Para scale, se considera que el padre tiene un tamaño de 1. Cualquier redimensionamiento del padre afecta a la escala y a la posición en proporción.
Las entities que no tienen component de shape son invisibles en la scene. Pueden usarse como envoltorios para manejar y posicionar varias entities como un grupo.
Para separar una entity hija de su parent, puedes asignar el parent de la entity a engine.RootEntity.
📔 Nota: Cuando trabajes con entities anidadas que están sincronizadas con otros players, usa la parentEntity() function en lugar de la parent entity en el Transform. Consulta Entities con parent
En el Scene Editor, puedes ver toda la jerarquía de entities anidadas en tu scene en el panel de la izquierda.

Obtener una entity por ID
Cada entity en tu scene tiene un número único id. Puedes recuperar un component que hace referencia a una entity específica desde el engine basándote en este ID.
📔 Nota: Los ids de entity entre 0 y 511 están reservados por el engine para entities fijas, como el avatar del player, la scene base, etc.
Por ejemplo, si el click de un player o un raycast impacta una entity, esto devolverá el id de la entity impactada, y puedes usar el comando anterior para obtener el component Transform de la entity que coincide 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 función engine.getEntityOrNullByName() 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 tree de la izquierda.
📔 Nota: Asegúrate de usar solo engine.getEntityOrNullByName() dentro de la main() function, en functions que se ejecuten después de main(), o en un system. Si se usa fuera de uno de esos contextos, las entities creadas en la UI del Scene Editor puede que aún no se hayan instanciado.
Tienes libertad para realizar cualquier acción sobre una entity recuperada mediante 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 component Name , 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 provocará un error.
Para evitar este error, puedes usar .createOrReplace en lugar de .create. Este comando sobrescribe cualquier component existente del mismo tipo si existe, y si no, crea un nuevo component igual que .create.
📔 Nota: Como .createOrReplace realiza una comprobación adicional antes de crear el component, siempre es más eficiente usar .create. Si estás seguro de que la entity todavía no tiene un component como el que vas a añadir, usa .create.
Acceder a un component desde una entity
Puedes acceder a los components de una entity usando la .get() o las funciones getMutable() .
El get() function obtiene una referencia de solo lectura al component. No puedes cambiar ningún valor de este component desde esta referencia.
Si quieres cambiar los valores del component, usa la función getMutable() 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 datos mutables para más detalles.
📔 Nota: Usa getMutable() solo si realmente vas a hacer cambios en los valores del component. En caso contrario, usa siempre get(). Esta práctica sigue los principios de data oriented programmingy puede ayudar de forma significativa al rendimiento de la scene.
El ejemplo anterior modifica directamente el valor de la x escala en el component Transform.
Si no estás completamente seguro de que la entity tenga el component que intentas recuperar, usa getOrNull() o getMutableOrNull().
📔 Nota: Evita usar getOrNull() o getMutableOrNull() cuando sea posible, ya que estas funciones implican comprobaciones adicionales y, por tanto, son menos eficientes que .get() y getMutable().
Si el component que intentas recuperar no existe en la entity:
get()ygetMutable()devuelve un error.getOrNull()ygetMutableOrNull()devuelveNull.
Eliminar un component de una entity
Para eliminar un component de una entity, usa el método deleteFrom() del tipo de component.
Si intentas eliminar un component que no existe en la entity, esta acción no generará ningún error.
📔 Nota: Para eliminar todos los components de una entity a la vez, consulta esta sección
Comprobar si hay un component
Puedes comprobar si una entity tiene 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 usarlo en lógica condicional en tu scene.
Comprobar cambios en un component
Usa la onChange function para ejecutar una función callback cada vez que los valores del component cambien para una determinada entity. Esto funciona con cualquier component, y es un gran atajo para ayudar a que tu código siga siendo legible.
La función callback puede incluir un parámetro de entrada que contenga el nuevo estado del component.
Si el component se elimina de la entity, entonces la función se llama con una entrada de undefined.
Obtener entities hijas
Para acceder a todas las entities que son hijas directas de una entity padre, usa getEntitiesWithParent. Toma como argumentos el engine y la parent entity y devuelve una lista de todas las entities que tienen esa entity concreta como parent. Ten en cuenta que solo devuelve children directos, no children de children.
Para acceder en su lugar a todos los descendientes de una Entity, sin importar qué tan profundamente anidados estén, usa la función getComponentEntityTree(). En lugar de recorrer manualmente la jerarquía nivel por nivel, esta función devuelve una lista plana de todos los descendientes que es fácil de iterar. También filtra para incluir solo las entities que tienen un Component dado o una lista de Components.
El getComponentEntityTree function toma tres parámetros:
engine: La instancia de engine que ejecuta las entitiesentity: La Entity raíz desde la que comenzarcomponent: El Component por el que filtrar (normalmenteTransformpara jerarquías espaciales)
La función devuelve un generador que emite cada Entity descendiente en la estructura de árbol. Solo se incluirán en los resultados las entities que tengan el Component especificado.
Puedes combinar esto con otras comprobaciones de Component para encontrar entities específicas en tu jerarquía:
Entidades reservadas
Ciertos ids de Entity están reservados para entidades especiales que existen en cada Scene. Se puede acceder a ellas mediante los siguientes alias:
engine.RootEntityengine.PlayerEntityengine.CameraEntity
📔 Nota: Evita referirte a estas entities antes de que se inicialicen. Para evitar este problema, refiérete a estas entities en la main() function, o en un System.
La Entity raíz
Todas las entities de la Scene son children de la engine.RootEntity, directamente o indirectamente.
Esta Entity no tiene un Component Transform, pero se usa para gestionar varios Components que representan ajustes más globales, como control del skybox, posición del cursor, o dimensiones de la pantalla.
La Entity player
El engine.PlayerEntity entity representa el avatar del player.
Obtener el Transform Component del player para obtener la posición y rotación actuales del player, consulta datos de usuario. El Transform del player es de solo lectura; para modificarlo usa la movePlayerTo() function, aprende más.
También puedes adjuntar objetos al player estableciéndolos como children de esta entity, aunque la Attach to Player suele ser la mejor opción para eso.
La Entity camera
El engine.CameraEntity entity representa la camera del player.
Obtener el Transform Component de la camera para obtener la posición y rotación de la camera. El Transform de esta entity también es de solo lectura. Para modificar el ángulo o la posición de la camera, usa una cámara virtual.
También puedes obtener el CameraMode Component para saber si el player está usando el modo de camera en primera o tercera persona, consulta modo de camera.
Última actualización