跳到主要内容

<pc-model>

<pc-model> 定义从 GLB 文件实例化模型的实体。

导出、压缩、查看结构和调整的完整流程详见加载模型。

用法
  • 必须直接位于 <pc-scene>、<pc-entity>、另一模型或 <pc-node> 下。
  • 可包含多个 <pc-node>,绑定内部节点以覆盖属性、添加组件或挂接内容。
  • 可包含实体和模型子项,以及每类一个组件,规则与 <pc-entity> 相同。

模型本身是实体宿主,不仅是加载器。它创建独立宿主,将 GLB 内容放在其下,因此可直接包含组件和子项:

<pc-model name="t-rex" asset="t-rex" scale="3 3 3">
<pc-anim></pc-anim>
</pc-model>

entity 是稳定宿主,从启动开始存在,asset 变化和重载后仍保留全部组件及子项。GLB 内容则单独通过 contentEntity 访问。

position、rotation 和 scale 属于宿主,即实例摆放,与资源根的原始变换组合,而不是替换。

属性​

支持 <pc-entity> 全部属性及 onclick/onpointer*,另增加 asset。

属性类型默认值说明
asset资源 ID-必须引用 container 资源
enabledBoolean(布尔)"true"模型启用状态
nameString(字符串)-宿主名称
positionVector3"0 0 0"局部位置 X Y Z
rotationVector3"0 0 0"局部角度制欧拉角 X Y Z
scaleVector3"1 1 1"局部缩放 X Y Z
tagsString(字符串)-逗号分隔标签

事件​

通过 addEventListener() 或 oneventname property 监听。

事件说明
load每次容器实例化完成触发,包括 asset 修改后的重建
error容器失败时触发 ErrorEvent。若查询前资源已失败,message 只报告该事实;原始引擎错误见资源 error

两者不冒泡,可直接监听或在祖先捕获多个模型。

宿主注册为拾取目标,因此也支持实体的九个指针事件及内联处理,无需包装或 pc-node 即可使整模型可点击:

<pc-model asset="t-rex" onclick="this.setAttribute('scale', '2 2 2')"></pc-model>

没有绑定部件时,命中模型任意位置以 pc-model 为目标;有 pc-node 时则以节点为目标。均向元素树冒泡,祖先无需模型自身监听也能收到。

就绪表示当前选择已结束:成功实例化、失败或未指定 asset 均包括。id 无匹配则警告且永不就绪。宿主 entity 始终非空,不能区分成功与否,应监听 error 或检查 contentEntity:

const model = await whenReady('pc-model');
if (!model.contentEntity) {
// no asset, or the load failed
}

动画​

直接在模型内放 <pc-anim>,空标签按轨道名添加全部动画并播放第一段:

<pc-model asset="robot">
<pc-anim></pc-anim>
</pc-model>

组件挂在宿主,无需包装。可添加 <pc-anim-clip> 自定义名称、速度、循环或外部来源。

可询问组件,检查导出后有哪些动画:

import { whenReady } from '@playcanvas/web-components';

const anim = await whenReady('pc-anim');
console.log(anim.clips); // ['Walk', 'Idle']

按包名导入需要 import map 配置,详见代码访问。容器无动画会警告,名称带点的轨道也会跳过并警告,因此不写代码也可查看控制台。

示例​

带骨骼动画的 GLB,由内嵌 pc-anim 播放,拖动可环绕:

实时示例
<pc-app>
<pc-asset src="https://cdn.jsdelivr.net/npm/[email protected]/scripts/esm/camera-controls.mjs"></pc-asset>
<pc-asset src="https://developer.playcanvas.com/assets/t-rex.glb" id="t-rex"></pc-asset>
<pc-material id="floor" diffuse="#3a3f4b"></pc-material>
<pc-scene>
<pc-entity name="camera" position="2.5 1.5 3.5">
<pc-camera clear-color="#2a2d36"></pc-camera>
<pc-script>
<pc-script-instance name="cameraControls" focus-point="0 1.2 0" pitch-range="-90 0" zoom-range="1.5 10"></pc-script-instance>
</pc-script>
</pc-entity>
<pc-entity name="light" rotation="45 30 0">
<pc-light cast-shadows normal-offset-bias="0.05" shadow-bias="0.2" shadow-distance="20" intensity="1.5"></pc-light>
</pc-entity>
<pc-entity name="ground" scale="30 30 30">
<pc-render type="plane" material="floor"></pc-render>
</pc-entity>
<pc-model name="t-rex" asset="t-rex" scale="1.5 1.5 1.5">
<pc-anim></pc-anim>
</pc-model>
</pc-scene>
</pc-app>

要修改内部节点,为各目标嵌套 <pc-node>:

<pc-model asset="car">
<!-- Hide the ground plane the GLB was exported with -->
<pc-node name="Plane" enabled="false"></pc-node>
</pc-model>

JavaScript 接口​

可以通过 ModelElement API创建和操作元素。

pc-model 也适合作为模板预制体根,AR 热狗风暴据此生成投射物,详见模板复用。

两个实体​

模型暴露两个实体,注意区别:

属性含义
entity元素创建并代表的宿主,启动后非空,asset 改变仍稳定,组件和额外子项挂在这里
contentEntity宿主下的 GLB 实例化根,加载成功前为 null,每次重载替换

因此组件放到 entity,查询文件内容则从 contentEntity 开始:

const model = await whenReady('pc-model');

model.entity.anim; // the component a nested <pc-anim> added
model.contentEntity.name; // the GLB root's own name, e.g. 'Sketchfab_model'

hierarchy() 和 pc-node 查找仅限内容根,宿主不出现在打印树、path 或名称查找中。

检查层级​

hierarchy() 报告真实实例化树,也是 pc-node 的匹配依据,不一定等于源文件名称。加载模型有完整案例,下面给出参考:

import { whenReady } from '@playcanvas/web-components';

const model = await whenReady('pc-model');
console.log(String(model.hierarchy()));
Car
├─ FrontAxle
│ └─ Wheel [0] (render) {defaultGlbMaterial}
├─ RearAxle
│ └─ Wheel [1] (render) {defaultGlbMaterial}
├─ Wing
└─ Wing1

每行包含节点名,有同名时带 index,括号列组件,花括号列材质。例如两个 Wheel 用 index=0 和 1 区分,Wing1 是引擎为第二个同名同级项添加后缀。

返回纯数据树根;尚未实例化、失败或元素移出文档时为 null。各节点包含:

属性类型说明
nameString实例化名称,pc-node 按它查找。无名节点生成 node_index,同名同级项会重命名
pathString模型根下的斜杠分隔路径,直接位于模型内的 pc-node 返回此路径,根路径为自身名称
indexNumber全模型深度优先顺序中的同名索引。嵌套 pc-node 则仅在外层节点子树内查找、计数并报告路径
componentsString[]已排序组件类型,例如 render
materialsObject[]Render 各网格实例按组件顺序对应的 index、name 对象,没有 Render 则为空
childrenObject[]子节点
toString()Function将当前子树打印为上述形式,String(node) 可打印任意分支

材质 name 是当前运行时标签,并非唯一标识。未命名为 Untitled,无材质图元用共享 defaultGlbMaterial,无导出法线会创建带 -flatShaded 后缀的副本,重复名仍重复,脚本清空分配则为 null。index 才无歧义。两者供节点材质覆盖选择,替换材质会报告其 name,建议显式设置以便识别。

树是每次调用重新计算的快照,不跟踪后续修改,改变快照也不影响场景。纯数据可 JSON.stringify,方便日志、差异比较和测试。

另请参阅​

示例:GLB 加载器、GLB 动画和产品查看器。