> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/shape-components.md).

# Componentes de forma

Aprende sobre los diferentes components que dan a las entities su forma 3D y su colisión.

Las escenas tridimensionales en Decentraland se basan en el [modelo Entity-Component](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system) , donde todo en una scene es un *entity*, y cada entity puede incluir *components* que dan forma a sus características y funcionalidad.

La forma renderizada de una entity está determinada por el component que usa.

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-417a02dcf0fd40f5032551a0c6996becac7e7166%2Fecs-simple-components-new.png?alt=media\&token=181a73c9-363a-4328-9874-6fed49447dc3)

## Usa el Scene Editor en Creator Hub

La forma más sencilla de darle una forma a una entity es usar el Scene Editor. Puedes añadir un **Mesh Renderer** component para proporcionar una forma primitiva, o un **GLTF** component para referenciar un modelo 3D desde un archivo. Consulta [Add Components](/creator/content-creator-es/scene-editor/construir/components.md#add-components).

## Formas primitivas

Se pueden añadir varias formas básicas, a menudo llamadas *primitivas*a una entity dándole un `MeshRenderer` component.

Las siguientes formas están disponibles. Varias formas incluyen campos adicionales opcionales, específicos de esa forma.

* **caja**:

  Usa `MeshRenderer.setBox()`, pasando la entity. Pasa `uvs` como un campo opcional adicional para mapear la alineación de la textura. Consulta [materials](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md) para obtener más detalles.
* **plano**:

  Usa `MeshRenderer.setPlane()`, pasando la entity. Pasa `uvs` como un campo opcional adicional para mapear la alineación de la textura. Consulta [materials](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md) para obtener más detalles.
* **esfera**:

  Usa `MeshRenderer.setSphere()`, pasando la entity.
* **cilindro**:

  Usa `MeshRenderer.setCylinder()`, pasando la entity. Pasa `radiusTop` y `radiusBottom` como campos opcionales adicionales para modificar el cilindro.

  CONSEJO: Establece cualquiera de los dos `radiusTop` o `radiusBottom` en 0 para crear un cono.

El siguiente ejemplo crea un cubo:

```ts
const myCube = engine.addEntity()

Transform.create(myCube, {
	position: Vector3.create(8, 1, 8),
})

MeshRenderer.setBox(myCube)
```

El siguiente ejemplo crea un cilindro con un `radiusTop` de 0, lo que produce un cono:

```ts
const myCone = engine.addEntity()

Transform.create(myCone, {
	position: Vector3.create(8, 1, 8),
})

MeshRenderer.setCylinder(myCone, 1, 0)
```

Las formas primitivas no incluyen materials. Para darle un color o una texture, debes asignar un [componente material](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md) a la misma entity.

Para hacer que una primitive sea clickable, o para evitar que los jugadores la atraviesen, debes darle a la entity un *collider* mediante un [MeshCollider](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/colliders.md) component.

Para cambiar la forma de una entity que ya tiene un `MeshRenderer` component, ejecuta `MeshRenderer.setBox()` o cualquiera de las otras funciones auxiliares y sobrescribirá la forma original. No hace falta eliminar el `MeshRenderer` original ni usar la sintaxis avanzada.

```ts
const myCube = engine.addEntity()

Transform.create(myCube, {
	position: Vector3.create(8, 1, 8),
})

MeshRenderer.setBox(myCube)

// sobrescribir la forma
MeshRenderer.setSphere(myCube)
```

{% hint style="warning" %}
**📔 Nota**: El `MeshRenderer` component debe importarse mediante

> `import { MeshRenderer } from "@dcl/sdk/ecs"`

Consulta [Imports](/creator/content-creator-es/scenes-sdk7/primeros-pasos/coding-scenes.md#imports) para ver cómo gestionar esto fácilmente.
{% endhint %}

## Modelos 3D

Para formas más complejas, puedes crear un modelo 3D en una herramienta externa como Blender y luego importarlos en *.glTF* o *.glb* (binario *.glTF*). [glTF](https://www.khronos.org/gltf) (GL Transmission Format) es un proyecto abierto de Khronos que proporciona un formato común y extensible para assets 3D que es a la vez eficiente y altamente interoperable con las tecnologías web modernas.

Para añadir un modelo externo a una scene, añade un `GltfContainer` component a una entity y establece su `src` en la ruta del archivo glTF que contiene el modelo.

```ts
const houseEntity = engine.addEntity()

GltfContainer.create(houseEntity, {
	src: 'models/House.gltf',
})
```

El `src` es obligatorio, debes darle un valor al construir el component. En el ejemplo anterior, el modelo está ubicado en una `models` carpeta en el nivel raíz de la carpeta del proyecto de la scene.

{% hint style="info" %}
**💡 Consejo**: Recomendamos mantener tus modelos separados en la `assets/scene/models` carpeta dentro de tu scene.
{% endhint %}

Los modelos glTF pueden incluir sus propias textures, materials, colliders y animations integradas. Consulta [Modelos 3D](https://github.com/decentraland/docs/blob/main/creator/3d-modeling/3d-models.md) para obtener más información sobre esto. Para sobrescribir los materials de un modelo, usa el [GltfNodeModifiers](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md#modify-gltf-materials) component. Consulta [Modificar materials de glTF](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md#modify-gltf-materials) para obtener más detalles.

Para evitar que los jugadores atraviesen un modelo 3D, o para hacer que un modelo sea clickable, debes tener un [collider](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/colliders.md)collider, que puede estar integrado en el modelo o proporcionado mediante un `MeshCollider` component.

Ten en cuenta que todos los modelos, sus shaders y sus textures deben estar dentro de los parámetros de las [limitaciones de la scene](/creator/content-creator-es/scenes-sdk7/optimizacion/scene-limitations.md).

{% hint style="warning" %}
**📔 Nota**: El `GltfContainer` component debe importarse mediante

`import { GltfContainer } from "@dcl/sdk/ecs"`

Consulta [Imports](/creator/content-creator-es/scenes-sdk7/primeros-pasos/coding-scenes.md#imports) para ver cómo gestionar esto fácilmente.
{% endhint %}

### Cargando previamente un modelo 3D

En algunos casos, se añade un modelo 3D personalizado a la scene, pero no se usa de inmediato. Por ejemplo, un modelo personalizado de silla puede cargarse solo cuando el player interactúa con otro objeto. En este escenario, la primera interacción podría tardar un poco hasta que termine de descargarse y cargarse el modelo.

Para evitar esto, usa el `AssetLoad.create` método para asegurar que el asset se descargue antes de que se necesite.

```ts
import { AssetLoad } from "@dcl/sdk/ecs"

AssetLoad.create(engine.RootEntity, {
  assets: [
    "assets/scene/bundle1/explosion.glb",
  ],
})
```

Para más información, consulta la [Pre Load Resources](/creator/content-creator-es/scenes-sdk7/optimizacion/pre-load-resources.md) documentación.

### Bibliotecas gratuitas para modelos 3D

En lugar de crear tus propios modelos 3D, también puedes descargarlos de varias bibliotecas gratuitas o de pago.

Para ayudarte a empezar, a continuación tienes una lista de bibliotecas con contenido gratuito o relativamente económico:

* [IWB Catalog](https://dcl-iwb.co/)
* [Asset Ovi](https://assetovi.com/)
* [Assets from the Builder](https://github.com/decentraland/builder-assets/tree/master/assets)
* [SketchFab](https://sketchfab.com/)
* [Clara.io](https://clara.io/)
* [Archive3D](https://archive3d.net/)
* [SketchUp 3D Warehouse](https://3dwarehouse.sketchup.com/)
* [Thingiverse](https://www.thingiverse.com/) (modelos 3D hechos principalmente para impresión 3D, pero adaptables a Virtual Worlds)
* [ShareCG](https://www.sharecg.com/)
* [CGTrader](https://www.cgtrader.com/)

{% hint style="warning" %}
**📔 Nota**: Presta atención a las restricciones de licencia que tiene el contenido que descargues.
{% endhint %}

Ten en cuenta que en varios de estos sitios puedes elegir en qué formato descargar el modelo. Elige siempre *.glTF* formato si está disponible. Si no está disponible, debes convertirlos a *glTF* antes de poder usarlos en una scene. Para eso, recomendamos importarlos en Blender y exportarlos como *.glTF* desde allí.

### Optimiza modelos 3D

Para asegurarte de que los modelos 3D en tu scene se carguen más rápido y ocupen menos memoria, sigue estas prácticas recomendadas:

* Guarda tus modelos en *.glb* formato, que es una versión más ligera de *.gltf*.
* Si tienes varios modelos que comparten las mismas textures, exporta tus modelos con las textures en un archivo separado. De ese modo, varios modelos pueden hacer referencia a un único archivo de texture que solo necesita cargarse una vez.
* Si tu scene tiene entities que aparecen y desaparecen, puede ser una buena idea hacer pool de esas entities y mantenerlas bajo tierra, o a una escala de 0. Esto les ayudará a aparecer más rápido; la contrapartida es que ocuparán memoria cuando no estén en uso. Consulta [entities and components](/creator/content-creator-es/scenes-sdk7/arquitectura/entities-components.md#pooling-entities-and-components)

## Estirar una forma

Las formas primitivas y los modelos 3D tienen dimensiones predeterminadas que puedes alterar cambiando la escala en el `Transform` component.

```ts
const primitiveEntity = engine.addEntity()

MeshRenderer.setBox(primitiveEntity)

Transform.create(primitiveEntity, {
	position: { x: 8, y: 1, z: 8 },
	scale: { x: 4, y: 0.5, z: 4 },
})
```

## Hacer invisible

Puedes hacer invisible una entity dándole a una entity un `VisibilityComponent`, con su propiedad `visible` establecida en *false*.

```ts
const myEntity = engine.addEntity()
Transform.create(myEntity, {
	position: Vector3.create(4, 0, 4),
})
MeshRenderer.setBox(myEntity)

VisibilityComponent.create(myEntity, { visible: false })
```

El `VisibilityComponent` funciona igual para entities con formas primitivas y con `GLTFContainer` components.

Si una entity es invisible, su collider puede bloquear el camino de un jugador y/o impedir hacer clic en entities que estén detrás, según las collision layers asignadas al collider.

### Propagar visibilidad

Puedes usar el `propagateToChildren` campo en el `VisibilityComponent` para aplicar una configuración a cada child en el árbol de children de la entity. Si `propagateToChildren` se establece en *true*se establece en true, estos ajustes afectan a todos los children en todos los niveles inferiores. Esto puede ahorrarte mucho trabajo tedioso al marcar cada child entity como invisible o visible también.

```ts
// Entity padre (explícitamente invisible)
const parentEntity = engine.addEntity()
Transform.create(parentEntity, {
	position: Vector3.create(4, 0, 4),
})
MeshRenderer.setBox(parentEntity)
VisibilityComponent.create(parentEntity, { visible: false, propagateToChildren: true })

// Entity child (implícitamente invisible por el padre)
const child = engine.addEntity()
Transform.create(child, {
	position: Vector3.create(0, 1, 0),
	parent: parentEntity
})
MeshRenderer.setBox(child)
```

{% hint style="warning" %}
**📔 Nota**: Si una entity tiene su propio `VisibilityComponent`, esto sobrescribe cualquier configuración de los padres.

Si una entity no tiene su propio `VisibilityComponent`, entonces su visibilidad la determina su parent más cercano con un `VisibilityComponent` y `propagateToChildren` establecido en *true*.
{% endhint %}

## Estado de carga

Si un modelo 3D es bastante grande, puede tardar un tiempo apreciable en renderizarse; este tiempo puede variar según el hardware del player y muchos otros factores. A veces necesitas asegurarte de que un modelo haya terminado de cargarse antes de realizar otra acción. Por ejemplo, si quieres teletransportar al player a una plataforma en el cielo, primero debes asegurarte de que la plataforma esté completamente renderizada antes de mover al player allí, o de lo contrario el player podría caer directamente a través de la plataforma.

Para comprobar si un modelo 3D ha terminado de renderizarse, revisa el `GltfContainerLoadingState` component de la entity. Este component está pensado para ser de solo lectura, y existe en cualquier entity que también tenga un `GltfContainer`component.

Este component tiene una sola propiedad llamada `currentState`, que contiene un valor del `LoadingState` enum.

El siguiente ejemplo usa un system para comprobar periódicamente el estado de carga del modelo 3D de una entity. Si el estado es `LoadingState.FINISHED`, quizá quieras ejecutar ahí lógica personalizada y terminar la ejecución del system.

```ts
export function main() {
	const meshEntity = engine.addEntity()
	GltfContainer.create(meshEntity, { src: 'models/Monster.glb' })
	engine.addSystem((deltaTime) => {
		const loadingState = GltfContainerLoadingState.getOrNull(meshEntity)
		if (!loadingState) return
		switch (loadingState.currentState) {
			case LoadingState.LOADING:
				console.log('mesh ESTÁ CARGÁNDOSE')
				break
			case LoadingState.FINISHED:
				console.log('mesh HA TERMINADO')
				// Ejecutar lógica personalizada
				break
			case LoadingState.FINISHED_WITH_ERROR:
				console.log('mesh HA TERMINADO PERO PUEDE TENER PROBLEMAS')
				break
			case LoadingState.UNKNOWN:
				console.log('mesh ESTÁ EN UN ESTADO DESCONOCIDO')
				break
		}
	})
}
```

## Sintaxis avanzada

La sintaxis completa para crear un `MeshRenderer` component, sin ningún helper para simplificarla, se ve así:

```ts
MeshRenderer.create(myBox, {
	mesh: {
		$case: 'box',
		box: { uvs: [] },
	},
})

MeshRenderer.create(myPlane, {
	mesh: {
		$case: 'plane',
		plane: { uvs: [] },
	},
})

MeshRenderer.create(myShpere, {
	mesh: {
		$case: 'sphere',
		sphere: {},
	},
})

MeshRenderer.create(myCylinder, {
	mesh: {
		$case: 'cylinder',
		cylinder: {},
	},
})
```

Así es como el protocolo base interpreta los componentes MeshRenderer. Las helper functions abstraen esto y exponen una sintaxis más amigable, pero detrás de escena generan esta sintaxis.

El `$case` campo te permite especificar uno de los tipos permitidos. Cada tipo admite un conjunto distinto de parámetros. En el ejemplo anterior, el `caja` tipo admite un `uvs` campo.

Los valores admitidos para `$case` son los siguientes:

* `caja`
* `plano`
* `esfera`
* `cilindro`

Dependiendo del valor de `$case`, es válido definir el objeto para la forma correspondiente, pasando cualquier propiedad relevante.

Para añadir un `MeshRenderer` component a una entity que posiblemente ya tenga una instancia de este component, usa `MeshRenderer.createOrReplace()`. Las helper functions como `MeshRenderer.setBox()` se encargan de sobrescribir las instancias existentes del component, pero ejecutar `MeshRenderer.create()` en una entity que ya tiene este component devuelve un error.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/shape-components.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
