# Uso del Component Script

Con el nuevo Script Component, es posible crear Entities que ejecutan código personalizado desde dentro de la propia entity.

Script Components permiten la ejecución del comportamiento personalizado de una Entity sin necesidad de trabajar directamente sobre el `index.ts` y potencialmente otros archivos.

## Configuración del Script Component

1. Añade el Script Component a una Entity haciendo clic en el `+` botón y selecciónalo. Crea un nuevo Script haciendo clic en **+ Add New Script Module** y elige un nombre, o usa el File Path (explora o arrastra y suelta un archivo existente).

![](/files/fb4c089300b8d10a363a2ccbe1e7a0cb7efc5b9f)

2. Haz clic en el botón CODE del component para abrir el editor de código predeterminado. Vamos a revisar su estructura. Para más detalles sobre cómo seleccionar y gestionar tu editor predeterminado, ve a [Combine with code](/creator/content-creator-es/scene-editor/extender-con-codigo/reference-items.md).

## Entendiendo la estructura del Script

Cuando el Script se abre por primera vez, tiene el siguiente código:

```ts
import { engine, Entity } from '@dcl/sdk/ecs'

export class BuildingScript {
  constructor(
    public src: string,
    public entity: Entity
  ) {}

  /**
   * Función start - llamada cuando el script se inicializa
   */
  start() {
    // Inicialización del Script
    console.log("BuildingScript initialized for entity:", this.entity);
  }

  /**
   * Función update - llamada en cada frame
   * @param dt - Delta time desde el último frame (en segundos)
   */
  update(dt: number) {
    // Llamada en cada frame
  }
}
```

La clase se compone de tres partes principales:

* El **constructor**,
* el **start()** method
* el **update()** método.

## Constructor

El constructor contiene los parámetros que quieres exponer y modificar dinámicamente desde tu escena en Creator Hub.

```ts
export class BuildingScript {
  constructor(
    public src: string,
    public entity: Entity,
    public numericVariable: number, 
  ) {}
...
}
```

Una vez guardado el archivo, el **Refresh** botón en el Script Component actualiza todos los cambios realizados.

<img src="/files/0139fec85ce41cea17ee4d09537305eff9a2686c" alt="Refresh button" data-size="line">

Una vez actualizado, el Script Component ahora muestra el `numericVariable` añadido en el código.

![](/files/859d44a080c110934a381696ac94ba213629523f)

## Parámetros

Si diferentes Entities usan el mismo archivo en el Script component, cada una sigue teniendo parámetros independientes: si la escena tiene dos edificios, `building1` y `building2`, ambos con un Script Component apuntando al `BuildingScript.ts` archivo, cada edificio tiene su propio `numericVariable` parámetro que puede modificarse de forma independiente.

{% hint style="warning" %}
**Nota importante**: No modifiques/elimine `public src: string` y `public entity: Entity`. Puedes añadir nuevas entradas siguiendo estas.
{% endhint %}

Los tipos permitidos para los parámetros del constructor son:

* `Entity`
* `string`
* `number`
* `boolean`
* `ActionCallback`

{% hint style="info" %}
**📔 Nota**: Tanto `public` y `private` parámetros del constructor se exponen a Creator Hub. La palabra clave `private` solo restringe el acceso dentro de la `BuildingScript` class. Para más detalles, consulta la documentación oficial de TypeScript sobre\
[Parameter Properties](https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties).
{% endhint %}

### Acceder a parámetros dentro del Script

Para acceder al valor de un parámetro desde tu código, usa la notación `this.definedParameter`. Por ejemplo, `this.numericVariable` o `this.entity`.

La plantilla predeterminada del Script incluye esta línea en el método start():

`console.log("BuildingScript initialized for entity:", this.entity);`.

Cámbiala así para registrar el valor de un valor que definiste en el constructor:

`console.log("BuildingScript initialized with numericVariable:`, `this.numericVariable);`

Ten en cuenta que cuando cambies el valor del parámetro en la UI de Creator Hub, también deberías ver reflejado ese valor registrado.

### Parámetros predeterminados

El constructor por defecto contiene un `src` y un `entity` parámetro, estos son muy útiles para el código de tu script:

* `this.entity` siempre se refiere a la entity que contiene el `Script` component, usa esto para acceder a información sobre la entity o añadir components a ella.
* `this.src` es la ruta donde se almacena el script. Esto es especialmente útil al crear Smart Items que están pensados para ser usados por otros. Usa este campo para construir la ruta a los archivos que vienen empaquetados con tu smart item, incluso si la ruta del smart item cambia o se renombra.

```ts
export class BuildingScript {
  constructor(
    public src: string,
    public entity: Entity,
  ) {}

  start() {
    Material.setPbrMaterial(this.entity, {
      texture: Material.Texture.Common({
        src: this.src + '/images/myImage.png',
      })
    });
  }
}
```

El script anterior obtiene la entity que posee el script y le aplica una texture. Obtiene la texture de un `.png` archivo que está empaquetado en la carpeta del smart item, en una subcarpeta llamada `/images`. Al usar `this.src`, nos aseguramos de que la ruta del archivo siempre sea conocida, sin importar si el smart item se importa a la scene bajo `/assets/custom/itemName` o `/assets/asset-packs/itemName`

### Tooltips en los parámetros

Añade tooltips a tus parámetros de entrada, para que los usuarios sepan para qué se usan estos campos o qué valores se aceptan. Los usuarios verán un icono de tooltip junto a cada campo en la UI del Script component, y podrán leer texto personalizado al pasar el cursor sobre el icono.

Para añadir tooltips a tu constructor, agrega un bloque comentado justo antes del constructor, y escribe una línea con `@param` más el nombre del campo, seguido de una descripción, para cada tooltip.

```ts
  /**
   * @param startDate - La fecha de inicio del evento en formato YYYY-MM-DD
   * @param yOffset - Cuántos metros por encima del ground mostrar el item
   */
  constructor(
    public src: string,
    public entity: Entity,
    public startDate?: string,
    public yOffset: number = 0.5,
  ) {
  }
```

Puede que necesites hacer clic en el icono de refresh en la UI del Script component para ver los cambios en tus tooltips.

<img src="/files/0139fec85ce41cea17ee4d09537305eff9a2686c" alt="Refresh button" data-size="line">

## Método start() & update()

El **start()** método contiene código que se ejecuta solo una vez, cuando se crea la Entity (en este caso, cuando la scene carga por primera vez).

Previsualiza la scene y revisa los logs (**Consejo**: puedes usar el `` ` `` atajo): Muestra el nuevo mensaje incluyendo el `numericVariable` parámetro.

![](/files/a2f24cfbf9d14757c4bf1fdd3cc1fcf86781d46c)

El **update()** método, por otro lado, ejecuta su código en cada frame del juego (igual que hacen los Systems). Por ejemplo, comprobar valores del `PlayerEntity` para activar comportamientos en el script.

El siguiente código imprime Logs en cada frame del juego en el que el `PlayerEntity` es mayor que el `numericVariable`definido previamente, que es proporcionado dinámicamente por el creador desde la UI del Script Component.

```ts
update(dt: number) {
    if (Transform.get(engine.PlayerEntity).position.y > this.numericVariable ) {
      console.log("The player's height is over ", this.numericVariable);
    }}
```

<img src="/files/dcd46f5797495472ee97d99761e62a2c0f24a310" alt="Update Method" data-size="line">

El primer log pertenece al método start(), indicando que establecimos numericVariable. El segundo pertenece al método update(), cuando el jugador está más alto que ese valor.

## Exponer Actions a Creator Hub

Es posible definir un `Action` dentro de un script de Script Component y hacer que esté accesible en la UI de Creator Hub. Esto permite la posibilidad de activar este `Action` con otra Entity.

```ts
  /**
   * Exponer esta action para ser activada
   * @action
   */
  exposedAction(creatorHubParameter: number) {
    console.log("Triggered from another entity using parameter: ", this.numericActionVariable);
  }
```

`creatorHubParameter` será expuesto como un `Action` parámetro para darle un valor personalizado. Después de actualizar el Script Component, la nueva action estará disponible como una opción en el dropdown de Actions.

![](/files/b029a4008f128c05d153a334cc69dc2a8aa37cc6)

Después de añadir la Action, cualquier Entity en Creator Hub puede activarla usando `Triggers`

![](/files/7233fc6d9614c1c271fb60396991027a4ac7012e)

{% hint style="info" %}
**📔 Nota**: Puedes añadir tantas Actions como necesites dentro del Script. Todas estarán accesibles de forma independiente desde el `Action` dropdown.
{% endhint %}

## Llamar métodos del Script desde fuera

Para llamar a un método del Script desde otro Script o desde `main.ts`, se deben seguir los siguientes pasos:

1. Create a `public` método dentro de la clase Script.
2. Ejecuta `npm run build` desde el directorio raíz de la scene.
3. Desde el archivo donde quieras usar el método público, añade `import { callScriptMethod } from '~sdk/script-utils'`.
4. Llama a `callScriptMethod` con los parámetros necesarios (en este caso, `someParamter`).

Aquí tienes un ejemplo con un `public` método expuesto

```ts
export class BuildingScript {
  constructor(
    public src: string,
    public entity: Entity,
    ...,
  ) {}

  public publicMethod(boolParameter: boolean, someNumberParameter: number) {
    if (boolParameter) {
      console.log("Public method called with parameter true!: ", someNumberParameter);
    } else {
      console.log("Public method called with parameter: false!", someNumberParameter);
    }
  }
...
}
```

Para llamarlo desde `main.ts`, usa:

```ts
import { callScriptMethod } from '~sdk/script-utils'


export function main() {
    const buildingEntity = engine.getEntityOrNullByName("building")
    if (buildingEntity) {
        const scriptMethod = callScriptMethod(
            buildingEntity,
            "assets/scene/Scripts/BuildingScript.tsx",
            "publicMethod",
            false,
            3,
        )

        scriptMethod
    }
}
```

Primero, la `main` función busca la `Entity` que tiene el Script component. Segundo, si la `Entity` existe, `callScriptMethod` se llama con los siguientes parámetros:

1. `entity`: `Entity` que tiene el `public` método.
2. `scriptPath`: `path` donde vive la `Script` class.
3. `methodName`: nombre del `public` método que se va a llamar.
4. `...args`: Argumentos del método. En este caso, hay dos. Deben añadirse en orden, uno después del otro.

Tercero, llamamos al `callScriptMethod`definido, en este caso, `scriptMethod`.

Con los valores de los parámetros dados, la salida es:

![](/files/00e6f9cbb52a19c0ca5c66a8c53c167011e73e9f)

{% hint style="info" %}
**📔 Nota**: Puedes seguir la misma lógica para llamar a un `public` método del Script desde otro script o archivo. Puedes usarlo para obtener o cambiar valores de `public` variables en la clase Script.
{% endhint %}

## Activar Actions de otras Entities desde un Script

Es posible usar un parámetro de tipo `ActionCallback` en el constructor de la clase Script. Esto permite activar el `Entity`de otra Entity `Action` definido a través de la UI de Creator Hub desde los métodos del Script.

En este ejemplo, `anotherEntityAction` se añade como un `public` parámetro.

```ts
export class BuildingScript {
  constructor(
    public src: string,
    public entity: Entity,
    public anotherEntityAction: ActionCallback,
    ...,
  ) {}
  ...
}
```

Un `Entity` y `Action` seleccionable ahora está disponible cuando el Script Component se actualiza en la UI de Creator Hub. `Sphere` es una Entity ya existente en la scene que tiene una action llamada `Escala`.

![](/files/47d0808c5c6df1d86875ec49ccad0f7cdaef0ee1)

La action de la otra Entity ahora es accesible en la clase Script. Puede usarse de muchas formas distintas. En el siguiente ejemplo, al presionar E se activará `this.anotherEntityAction` definiendo un `pointerEventsSystem` más cercano en el `start` método.

```ts
  start() {
    pointerEventsSystem.onPointerDown(
      {
        entity: this.entity,
        opts: {
          button: InputAction.IA_PRIMARY,
          hoverText: "Press E to trigger an Action from another Entity.",
        },
      },
      () => {
        this.anotherEntityAction();
      }
    );
  }
```

{% hint style="info" %}
**📔 Nota**: Combinar exponer y activar `Actions` es una herramienta muy poderosa. Puedes definir un Script Component en una Entity, exponer una action usando un `public` método, y luego activarla desde el Script Component de otra Entity usando un `ActionCallback` parámetro.
{% endhint %}

## See also

* [Smart items - Basics](/creator/content-creator-es/scene-editor/interactividad/smart-items.md)
* [Smart Items - Advanced](/creator/content-creator-es/scene-editor/interactividad/smart-items-advanced.md)
* [States and conditions](/creator/content-creator-es/scene-editor/interactividad/states-and-conditions.md)
* [Hacer inteligente cualquier item](/creator/content-creator-es/scene-editor/interactividad/make-any-item-smart.md)
* [Inicio rápido del SDK](/creator/content-creator-es/scenes-sdk7/primeros-pasos/sdk-101.md): sigue este mini tutorial para un curso intensivo rápido.
* [Flujo de trabajo de desarrollo](/creator/content-creator-es/scenes-sdk7/primeros-pasos/dev-workflow.md): lee esto para entender la creación de scenes de principio a fin.
* [Ejemplos](https://studios.decentraland.org/resources?sdk_version=SDK7): sumérgete directamente en scenes de ejemplo en funcionamiento.


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-es/scene-editor/extender-con-codigo/script-component.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
