跳到主要内容

实体组件系统

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

app.root 下的实体树包含相机、灯光和汽车,汽车下有车身和车轮;每个实体的组件按系统排列,app.systems 的渲染系统管理汽车、车身和车轮的渲染组件

这种模式称为实体组件系统(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 实体是场景图中的对象,而非单纯的标识符;组件同时包含数据和行为。

一个场景,四种实现方式​

下面的场景包含三个实体:相机、灯光和橙色立方体。相机抬高后向下倾斜,朝向立方体;立方体旋转了一定角度,可以看到三个面。

深色背景中的橙色立方体,展示顶面和两个侧面,光线来自左上方

按独立使用引擎配置应用,并注册渲染、相机和灯光组件系统后:

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);

无论采用哪种方式,最终都会在 app.root 下生成相同的实体树,每个实体包含一个组件。Editor、React 和 Web Components 会代你创建这些引擎对象,并提供在需要时访问它们的方式:

引擎编辑器ReactWeb 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 = falseInspector 中的字段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 属性

本节内容​

  • 实体:创建、命名、启用、销毁和复制实体。
  • 组件:内置组件,以及添加、修改、禁用和移除组件。
  • 层级与变换:坐标系、局部空间与世界空间、移动和旋转,以及父子关系。
  • 查找实体:通过名称、路径、标签、组件或脚本查找实体。

另请参阅​