实体组件系统
PlayCanvas 场景中的一切都是实体:观察场景的相机、照亮场景的灯光、每个模型、声音和界面元素,以及游戏中的对象。实体本身只是空间中一个带名称的点,拥有位置、旋转和缩放,并处于其他实体构成的层级中。组件为实体赋予能力:相机组件使实体成为相机,渲染组件在其位置绘制网格,刚体组件将其交给物理引擎处理,脚本组件则在实体上运行自定义代码。对于每种组件类型,应用都有一个系统,负责运行该类型的所有组件。

这种模式称为实体组件系统(Entity Component System,简称 ECS)。无论采用何种开发方式,你都会使用它:Editor、React 和 Web Components 创建的实体与组件,与直接调用引擎代码创建的完全相同。本节各页面先统一解释概念,再展示如何在这些开发方式中使用。
实体
实体是 Entity 类的对象。它拥有可用于查找的名称和标签,以及控制自身和所有后代启用或禁用的状态。实体的位置、旋转和缩放相对于父实体,因此移动实体时,其子实体也会一起移动。
场景中的实体构成一棵以 app.root 为根的树。将实体加入这棵树后,它才进入场景;在此之前,实体不会被绘制,其脚本也不会运行。参见层级与变换。
组件
组件为实体添加一种能力,并通过属性保存相关设置,例如 entity.light.color 或 entity.camera.fov。每个实体最多只能有一个同类型组件。如果要给对象添加两盏灯,可以创建两个子实体,分别添加灯光组件。
引擎内置约二十种组件,涵盖相机、灯光、渲染、声音、物理、动画、粒子和用户界面。实现自定义行为时,不需要编写新的组件类型,而应编写脚本,由脚本组件在实体上运行任意数量的脚本。
系统
每种组件类型都有一个 ComponentSystem 系统,负责创建、更新和销毁该类型的所有组件,并保存它们共享的设置。通常不需要直接操作系统,但共享设置是例外。例如,app.systems.rigidbody.gravity 表示作用于所有刚体的重力。
应用只运行已注册的系统。pc.AppBase 初始不包含任何系统,你需要列出所用系统,打包工具便能从构建中排除其余部分。pc.Application 则会注册全部内置系统,Editor、React 和 Web Components 也是如此。参见组件系统。
如果你熟悉 Unity,可以将实体对应为 GameObject,将组件对应为 Component,详见从 Unity 迁移。如果你熟悉 Unity DOTS 或 Bevy 等面向数据的 ECS,则需要注意:PlayCanvas 实体是场景图中的对象,而非单纯的标识符;组件同时包含数据和行为。
一个场景,四种实现方式
下面的场景包含三个实体:相机、灯光和橙色立方体。相机抬高后向下倾斜,朝向立方体;立方体旋转了一定角度,可以看到三个面。

- 引擎
- 编辑器
- React
- Web Components
按独立使用引擎配置应用,并注册渲染、相机和灯光组件系统后:
const camera = new pc.Entity('camera');
camera.addComponent('camera', {
clearColor: new pc.Color(0.11, 0.12, 0.17)
});
camera.setPosition(0, 1.1, 3.2);
camera.setEulerAngles(-20, 0, 0);
app.root.addChild(camera);
const light = new pc.Entity('light');
light.addComponent('light');
light.setEulerAngles(45, -30, 0);
app.root.addChild(light);
const material = new pc.StandardMaterial();
material.diffuse = new pc.Color(1, 0.55, 0.2);
material.update();
const box = new pc.Entity('box');
box.addComponent('render', { type: 'box', material: material });
box.setEulerAngles(0, 35, 0);
app.root.addChild(box);
- 在层级面板中选中 Root 实体,点击 + 并选择 Camera › Perspective。在检查器面板中,将 Position 设为 (0, 1.1, 3.2),Rotation 设为 (-20, 0, 0),并将相机组件的 Clear Color 设为深蓝色。
- 再次选中 Root,点击 + 并选择 Light › Directional Light,将 Rotation 设为 (45, -30, 0)。
- 再次选中 Root,点击 + 并选择 3D › Box,将 Rotation 设为 (0, 35, 0)。
- 创建一个 Diffuse 为橙色的材质,从资源面板将它拖到视口中的立方体上。
这些菜单项创建的实体已经包含名称所对应的组件。你可以通过 Inspector 中的 Add Component 按钮为任意实体添加更多组件。
import { Application, Entity } from '@playcanvas/react';
import { Camera, Light, Render } from '@playcanvas/react/components';
import { useMaterial } from '@playcanvas/react/hooks';
function Scene() {
const orange = useMaterial({ diffuse: '#ff8c33' });
return (
<>
<Entity name="camera" position={[0, 1.1, 3.2]} rotation={[-20, 0, 0]}>
<Camera clearColor="#1c1f2b" />
</Entity>
<Entity name="light" rotation={[45, -30, 0]}>
<Light type="directional" />
</Entity>
<Entity name="box" rotation={[0, 35, 0]}>
<Render type="box" material={orange} />
</Entity>
</>
);
}
export default function App() {
return (
<Application>
<Scene />
</Application>
);
}
<pc-app>
<pc-material id="orange" diffuse="#ff8c33"></pc-material>
<pc-scene>
<pc-entity name="camera" position="0 1.1 3.2" rotation="-20 0 0">
<pc-camera clear-color="#1c1f2b"></pc-camera>
</pc-entity>
<pc-entity name="light" rotation="45 -30 0">
<pc-light></pc-light>
</pc-entity>
<pc-entity name="box" rotation="0 35 0">
<pc-render type="box" material="orange"></pc-render>
</pc-entity>
</pc-scene>
</pc-app>
无论采用哪种方式,最终都会在 app.root 下生成相同的实体树,每个实体包含一个组件。Editor、React 和 Web Components 会代你创建这些引擎对象,并提供在需要时访问它们的方式:
| 引擎 | 编辑器 | React | Web Components | |
|---|---|---|---|---|
| 实体 | new pc.Entity('box') | 层级面板中的一项 | <Entity name="box"> | <pc-entity name="box"> |
| 在树中的位置 | parent.addChild(box) | 在层级面板中将其拖到父实体上 | 嵌套于父实体的 <Entity> 中 | 嵌套于父实体的 <pc-entity> 中 |
| 组件 | box.addComponent('render', { type: 'box' }) | Inspector 中的 Add Component | <Entity> 内的 <Render type="box" /> | <pc-entity> 内的 <pc-render type="box"> |
| 属性 | box.render.castShadows = false | Inspector 中的字段 | castShadows={false} | cast-shadows="false" |
| 自定义行为 | box.addComponent('script').create(Spin) | Script 组件中的脚本 | <Script script={Spin} /> | <pc-script> 中的 <pc-script-instance name="spin"> |
| 从代码访问引擎实体 | box | 实体上脚本中的 this.entity | <Entity> 的 ref | <pc-entity> 的 entity 属性 |
本节内容
- 实体:创建、命名、启用、销毁和复制实体。
- 组件:内置组件,以及添加、修改、禁用和移除组件。
- 层级与变换:坐标系、局部空间与世界空间、移动和旋转,以及父子关系。
- 查找实体:通过名称、路径、标签、组件或脚本查找实体。
另请参阅
- 脚本编程:为实体添加自定义行为。
- 从 Unity 迁移:Unity 的游戏对象、组件和预制体如何对应到 PlayCanvas。
- 层级面板与检查器面板:在编辑器中操作实体与组件。
<Entity/>和<pc-entity>:React 与 Web Components 实体参考。- Entity、Component 和 ComponentSystem:引擎 API 参考。