> 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-zh/chang-jing-bian-ji-qi/shi-yong-dai-ma-kuo-zhan/script-component.md).

# 使用脚本组件

使用 Script 组件赋予代码功能，而无需深入整个项目结构。

使用新的 Script Component，可以创建在实体内部执行自定义代码的 Entity。

Script Component 允许执行 Entity 的自定义行为，而无需直接操作 `index.ts` 以及可能的其他文件。

## 设置 Script Component

1. 通过点击 `+` 按钮并选择它，将 Script Component 添加到一个 Entity。通过点击 **+ Add New Script Module** 并选择一个名称，或者使用文件路径（浏览或拖放现有文件）来创建一个新的 Script。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-79378b201ff5d7fd7334d821c9c2ab0224da46b8%2Fnew-script-component.png?alt=media)

2. 点击组件中的 CODE 按钮以打开默认代码编辑器。我们来看看它的结构。有关如何选择和管理默认编辑器的更多详情，请前往 [与代码结合使用](/creator/content-creator-zh/chang-jing-bian-ji-qi/shi-yong-dai-ma-kuo-zhan/overview.md).

## 理解 Script 结构

当 Script 首次打开时，它包含以下代码：

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

export class BuildingScript {
  /**
   * 属性
   * 定义你希望在各个方法之间复用的类字段。
   * 示例用法：this.myVariable
   */
   // private myVariable: boolean = true

  /**
   * 构造函数 / 输入
   * 这里声明的参数会显示在 Creator Hub 中的 Script 组件 UI 里。
   * 支持的类型：Entity、String、Number、Boolean、ActionCallback 和 Slider
   * 对于用滑块编辑的数字，例如 public speed: Slider<0, 10, 0.5> = 1
   *
   * 注意：编辑此文件后，请点击 Script 组件 UI 中的刷新图标
   * 以查看更新后的输入项。
   *
   * 构造函数中的 `src` 和 `entity` 字段是内部引用所必需的。
   */
  constructor(
    public src: string,     // 请勿删除
    public entity: Entity,   // 请勿删除
    // 在下方添加你的自定义输入
  ) {}

  /**
   * start()
   * 在脚本初始化时调用一次。
   */
  start() {
    // 脚本初始化
    console.log("BuildingScript initialized for entity:", this.entity);
  }

  /**
   * update(dt)
   * 每一帧调用。
   * @param dt -（可选）自上一帧以来的时间差（秒）
   */
  update(dt: number) {
    // 每一帧调用
  }
}
```

这个类由三个主要部分组成：

* 该 **构造函数**,
* 该 **start()** 方法
* 该 **update()** 方法。

## 构造函数

构造函数包含你希望在 Creator Hub 场景中公开并动态修改的参数。

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

一旦文件保存， **Refresh** 按钮会更新所有已进行的更改。

<img src="https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-0e88676864e337ab55bf98ae8bd23e2775ec0c60%2Fscript-refresh-button.png?alt=media" alt="刷新按钮" width="360">

刷新后，Script 组件现在会显示 `numericVariable` ，它已添加到代码中。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-8729a660cd9b4cd056ff33ad0a28fefe1b7814b1%2Fparameter-script-component.png?alt=media)

## 参数

如果不同的 Entity 在 Script component 中使用同一个文件，它们仍然具有独立的参数：如果场景中有两座建筑， `building1` 和 `building2`，它们都拥有指向 `BuildingScript.ts` 文件的 Script Component，那么每座建筑都有自己可独立修改的 `numericVariable` 参数。

{% hint style="warning" %}
**重要说明**：不要修改/删除 `public src: string` 和 `public entity: Entity`。你可以在这些参数之后添加新的输入项。
{% endhint %}

构造函数参数允许的类型有：

* `Entity`
* `字符串`
* `数字`
* `布尔值`
* `ActionCallback`
* `Slider<Min, Max, Step>`

### 带滑块的数字参数

将数字参数写为 `Slider<Min, Max, Step>` ，即可使用滑块而不是普通数字输入框进行编辑。Creator Hub 会同时显示滑块和数字输入框。

```ts
constructor(
  public src: string,
  public entity: Entity,
  // 一个从 0 到 10、每次以 0.5 步进的滑块
  public speed: Slider<0, 10, 0.5> = 1,
) {}
```

* `Step` 是可选的，默认值为 `1`.
* 允许负数范围，例如 `Slider<-90, 90>`.
* 在运行时，该值是一个普通的 `数字`，因此 `this.speed` 的行为与任何其他数字参数相同。

{% hint style="info" %}
**📔 注意**： `public` 和 `private` 构造函数参数会公开给 Creator Hub。 `private` 关键字只会限制在 `BuildingScript` 类内部的访问。有关更多详情，请参阅 TypeScript 官方文档中的\
[参数属性](https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties).
{% endhint %}

### 在 Script 中访问参数

要从代码中访问参数值，请使用记法 `this.definedParameter`。例如， `this.numericVariable` 或 `this.entity`.

默认的 Script 模板在 start() 方法中包含这一行：

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

将其改成这样，以记录你在构造函数中定义的值：

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

请注意，当你在 Creator Hub UI 中更改该参数的值时，也应该能在此日志中看到该值的变化。

### 默认参数

构造函数默认包含一个 `src` 和一个 `实体` 参数，这些对于脚本中的代码非常有用：

* `this.entity` 始终指向包含 `脚本` 组件的实体，可用它来访问该实体的信息或向其添加组件。
* `this.src` 是脚本存储的路径。这在创建供他人使用的 Smart Items 时尤其有用。即使 Smart Item 的路径发生变化或被重命名，也可以使用此字段构建与该 Smart Item 一起打包的文件路径。

```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',
      })
    });
  }
}
```

上面的脚本会获取拥有该脚本的实体，并为其应用纹理。它从一个 `.png` 文件中获取该纹理，该文件打包在 Smart Item 文件夹中，位于名为 `/images`的子文件夹内。通过使用 `this.src`，我们可以确保文件路径始终可知，无论 Smart Item 是被导入到 `/assets/custom/itemName` 或 `/assets/asset-packs/itemName`

### 参数上的工具提示

为你的输入参数添加工具提示，这样用户就能知道这些字段是做什么的，或者接受哪些值。用户会在 Script 组件 UI 中看到每个字段旁边的工具提示图标，并且可以在将鼠标悬停在图标上时阅读自定义文本。

要为构造函数添加工具提示，请在构造函数之前添加一个注释块，并为每个工具提示写一行 `@param` ，再加上字段名称，然后是描述。

```ts
  /**
   * @param startDate - 事件开始日期，格式为 YYYY-MM-DD
   * @param yOffset - 要在地面上方显示该物体多少米
   */
  constructor(
    public src: string,
    public entity: Entity,
    public startDate?: string,
    public yOffset: number = 0.5,
  ) {
  }
```

你可能需要点击 Script 组件 UI 上的刷新图标，才能看到工具提示的更改。

<img src="https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-0e88676864e337ab55bf98ae8bd23e2775ec0c60%2Fscript-refresh-button.png?alt=media" alt="刷新按钮" width="360">

## start() 与 update() 方法

该 **start()** 方法包含的代码只会在 Entity 创建时执行一次（在本例中，是在场景首次加载时）。

预览场景并检查日志（**提示**：你可以使用 `` ` `` 快捷键）：它会显示包含 `numericVariable` 参数，将图像文件设为材质上的纹理。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-a8d756ab46337ed47bf6d1d7ae97641abd4cee64%2Fscript-log-message.png?alt=media)

该 **update()** 方法；而另一方面，它会在游戏的每一帧执行其代码（就像 Systems 一样）。例如，检查 `PlayerEntity` 的值以便在脚本中触发行为。

下面的代码会在游戏的每一帧打印日志，当 `PlayerEntity` 高于之前定义的 `numericVariable`，也就是创建者通过 Script Component UI 动态提供的值时。

```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="https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-07e4722b53743d2bac04744175a46fc25488cc36%2Fupdate-script-logs.png?alt=media" alt="Update Method" data-size="line">

第一条日志属于 start() 方法，表示我们设置了 numericVariable。第二条日志属于 update() 方法，当玩家高于该值时会打印。

## 将动作公开给 Creator Hub

可以在 Script Component 脚本中定义一个 `Action` ，并让它可在 Creator Hub 的 UI 中访问。这使得可以通过另一个 Entity 来触发这个 `Action` 。

```ts
  /**
   * 将此动作公开以便触发
   * @action
   */
  exposedAction(creatorHubParameter: number) {
    console.log("Triggered from another entity using parameter: ", this.creatorHubParameter);
  }
```

`creatorHubParameter` 将被公开为一个 `Action` 参数，以便为其赋予自定义值。刷新 Script Component 后，这个新动作将作为 Actions 下拉菜单中的一个选项可用。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-d7b71673260d80622c4b5635526aa3444d84ccff%2Fscript-component-action.png?alt=media)

添加该 Action 后，Creator Hub 中的任何 Entity 都可以使用它来触发 `触发器`

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-33aa38670114e43b0bb1beb493e2233642530167%2Fscript-component-action-trigger.png?alt=media)

{% hint style="info" %}
**📔 注意**：你可以在 Script 中添加任意多个 Action。所有这些都可以独立地通过 `Action` 下拉菜单访问。
{% endhint %}

## 从外部调用 Script 方法

要从另一个 Script 或从 `src/index.ts`调用 Script 方法，请遵循以下步骤：

1. 创建一个 `public` 方法放在 Script 类内部。
2. 运行 `npm run build` 来自场景根目录。
3. 在你想使用该 public 方法的文件中，添加 `import { callScriptMethod } from '~sdk/script-utils'`.
4. 调用 `callScriptMethod` 并传入所需参数（在本例中， `someParamter`).

下面是一个带有 `public` 公开方法

```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);
    }
  }
...
}
```

要从 `src/index.ts`调用它，请使用：

```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
    }
}
```

首先， `main` 函数会查找 `Entity` 拥有 Script 组件的实体。其次，如果 `Entity` 存在， `callScriptMethod` 将使用以下参数被调用：

1. `实体`: `Entity` 包含 `public` 方法。
2. `scriptPath`: `path` 的 `脚本` 类所在位置。
3. `methodName`：要调用的 `public` 方法名称。
4. `...args`：方法参数。本例中有两个。它们应按顺序依次添加。

第三，我们调用已定义的 `callScriptMethod`，在本例中， `scriptMethod`.

给出参数值后，输出为：

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-32c18509225406a1f8162b0d9719fc1e38ed8da0%2Fscript-component-public-method.png?alt=media)

{% hint style="info" %}
**📔 注意**：你可以遵循相同的逻辑，从另一个脚本或文件中调用一个 `public` Script 方法。你可以使用它来获取或更改 `public` Script 类中的变量值。
{% endhint %}

## 从 Script 中触发其他 Entity 的 Action

可以在 Script 类构造函数中使用类型为 `ActionCallback` 的参数。这允许从 Script 的方法中触发另一个 `Entity`的 `Action` 通过 Creator Hub UI 定义的内容。

在这个示例中， `anotherEntityAction` 被添加为 `public` 参数，将图像文件设为材质上的纹理。

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

一个可选择的 `Entity` 和 `Action` 现在在 Creator Hub UI 中刷新 Script Component 时可用了。 `Sphere` 是场景中一个已存在的 Entity，它有一个名为 `缩放`.

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-a264fa3fe8ceb754877b1022f0c653d3cb29ece6%2Fscript-component-action-callback.png?alt=media)

另一个 Entity 的 Action 现在可在 Script 类中访问。它可以有多种不同的用法。以下示例中，按下 E 将触发 `this.anotherEntityAction` ，方法是定义一个 `pointerEventsSystem` 在 `start` 方法。

```ts
  start() {
    pointerEventsSystem.onPointerDown(
      {
        entity: this.entity,
        opts: {
          button: InputAction.IA_PRIMARY,
          hoverText: "按 E 触发来自另一个 Entity 的 Action。",
        },
      },
      () => {
        this.anotherEntityAction();
      }
    );
  }
```

### 可选 Action 回调

一个 `ActionCallback` 创作者未连接的 `undefined`参数，其类型为 `ActionCallback | undefined`。调用前先检查，这样脚本无论 Action 是否连接都能正常工作：

```ts
if (this.anotherEntityAction) {
  this.anotherEntityAction();
}
```

{% hint style="info" %}
**📔 注意**：结合公开与触发 `操作` 是一个非常强大的工具。你可以在一个 Entity 上定义 Script Component，使用一个 `public` 方法公开一个 Action，然后从另一个 Entity 的 Script Component 中使用一个 `ActionCallback` 参数，将图像文件设为材质上的纹理。
{% endhint %}

## 另请参阅

* [智能项目 - 基础](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/smart-items.md)
* [智能物件 - 高级](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/smart-items-advanced.md)
* [状态和条件](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/states-and-conditions.md)
* [让任意项目变为智能项目](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/make-any-item-smart.md)
* [SDK 快速入门](/creator/content-creator-zh/chang-jing-sdk7/ru-men/sdk-101.md)：跟随这个迷你教程，快速入门。
* [开发工作流](/creator/content-creator-zh/chang-jing-sdk7/ru-men/dev-workflow.md)：从头到尾了解场景创建。
* [示例](https://studios.decentraland.org/resources?sdk_version=SDK7)：直接查看可工作的示例场景。


---

# 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 dynamically by asking a question.

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

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-bian-ji-qi/shi-yong-dai-ma-kuo-zhan/script-component.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
