> 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-sdk7/jia-gou/composites.md).

# 复合体

在运行时从复合文件生成一棵实体与组件树

一个 *复合体* 是一个描述以下树的文件 [实体和组件](/creator/content-creator-zh/chang-jing-sdk7/jia-gou/entities-components.md)。你无需编写代码逐个创建每个实体，可以将该结构存储在一个复合体文件中，并通过一次调用将整个结构生成出来。

你可能已经在不知不觉中使用过复合体：

* 每个场景都有一个 `main.composite` 文件。它保存了你在 [场景编辑器](/creator/content-creator-zh/chang-jing-bian-ji-qi/kai-shi-shi-yong/about-editor.md)。当你的场景启动时，此文件会自动加载。
* [自定义物品](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/custom-items.md) 会保存为 `composite.json` 文件。每个自定义物品都是一个可在不同场景间复用的复合体。

本页介绍如何在运行时通过代码生成复合体，例如将自定义物品作为场景逻辑的一部分动态生成。

## 生成复合体

生成复合体分两步： **加载** 复合体文件，然后 **生成** 它。加载是异步的，生成是同步的，因此模式始终是先加载后生成：

```ts
import { engine, Composite, getCompositeProvider } from "@dcl/sdk/ecs";

export async function spawnBarrel() {
  const src = "barrel.composite";
  const provider = getCompositeProvider();
  if (!provider || !provider.loadComposite) return;

  // 1. 从其文件中加载复合体
  const resource = await provider.loadComposite(src);

  // 2. 生成它：创建其所有实体和组件
  const barrel = Composite.instance(engine, resource, provider);
  return barrel;
}
```

`provider.loadComposite(src)` 读取复合体文件并将其加载到内存中。在使用 `@dcl/sdk`， `getCompositeProvider()` 中的函数 `@dcl/sdk/ecs`.

`Composite.instance()` 然后会创建复合体中描述的所有实体及其所有组件，并返回 **根实体** 生成树的根实体。之后可使用此返回的实体读取或更改组件，例如重新定位或移除已生成的物品。

{% hint style="info" %}
**💡 提示**：若要在不编写代码的情况下执行相同操作，请使用 **生成实体** 操作，见 [关于生成实体](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/smart-items-advanced.md#about-spawning-entities).
{% endhint %}

{% hint style="warning" %}
**📔 注意**：你必须先加载复合体，才能生成它。 `Composite.instance()` 是同步的，并且只能生成已在内存中的复合体。只有 `main.composite` 与你的场景捆绑并从一开始就可用；任何其他复合体文件都必须先通过 `loadComposite()` 先加载。若要同步检查某个复合体是否已可用，请使用 `provider.getCompositeOrNull(src)`.

`loadComposite()` 是幂等的：它会按其 `src` 字符串作为键，因此再次使用相同路径调用时不会重新加载文件，而是返回已加载的复合体。你可以在每次生成前安全调用它，而无需担心重复加载同一个文件。
{% endhint %}

### 生成到现有实体上

默认情况下 `Composite.instance()` 会创建一个新实体来承载生成的树。传入一个 `rootEntity` 作为选项，即可生成到你已有的实体上：

```ts
// 直接在场景根节点生成复合体，不使用包装实体
const barrel = Composite.instance(engine, resource, provider, {
  rootEntity: engine.RootEntity,
})
```

## 定位已生成的复合体

若要将已生成的复合体放置到指定的位置、旋转或缩放，请在返回的根实体上设置一个 `Transform` 组件，该根实体由以下方法返回： `Composite.instance()`.

```ts
import { engine, Composite, getCompositeProvider, Transform } from "@dcl/sdk/ecs";
import { Vector3 } from "@dcl/sdk/math";

export async function spawnBarrel() {
  const src = "barrel.composite";
  const provider = getCompositeProvider();
  if (!provider || !provider.loadComposite) return;

  const resource = await provider.loadComposite(src);

  // 在指定位置生成复合体
  const barrel = Composite.instance(engine, resource, provider);
  Transform.createOrReplace(barrel, {
    position: Vector3.create(8, 0, 8),
  });
}
```

{% hint style="warning" %}
**📔 注意**: `Transform.createOrReplace()` 会替换根实体现有的 Transform 组件。只有根实体会受到影响，子实体会保持相对于根实体的位置不变。
{% endhint %}

## 当前限制：嵌套复合体

生成适用于自包含复合体和自定义物品。复合体可以从其某个实体引用另一个复合体，但 `loadComposite()` 不会 **不是** 递归处理这些嵌套引用：它只会加载你传入的文件。

在生成时， `Composite.instance()` 会递归处理内存中已存在的嵌套引用。如果某个嵌套复合体尚未加载（除了 `main.composite`，即与你的场景捆绑的唯一复合体），则该分支会记录警告并被跳过。若要生成带有嵌套引用的复合体，请先为每个被引用的文件调用 `loadComposite()` ——或者更简单地，让你生成的复合体保持自包含。

## 相关页面

* [实体与组件](/creator/content-creator-zh/chang-jing-sdk7/jia-gou/entities-components.md) ——复合体所描述的构建块。
* [自定义物品](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/custom-items.md) ——以复合体形式存储的可复用物品。
* [智能物品 - 高级](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/smart-items-advanced.md#about-spawning-entities) ——使用“生成实体”操作，无需代码即可生成复合体。
* [场景文件](/creator/content-creator-zh/chang-jing-sdk7/xiang-mu-lei-xing/scene-files.md) ——其中 `main.composite` 位于你的场景项目中。


---

# 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-sdk7/jia-gou/composites.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.
