跳转到内容

对象生命管理

相关参考:Scene API / 对象层级与生命周期

动态创建出来的对象,不只是“创建并显示”这么纯粹,还要区分它们何时加入场景、何时移除、何时真正销毁。

四个核心动作

createXxx

js
const image = await api.createImage(arrayBuffer);

createXxx()都属于对象创建。不同对象类型,API名称不一样。详细查看动态创建内容

add

把一个新创建的对象加入当前场景,使其可见:

js
await api.add(image);

createXxx() API 返回对象后,并不会立即可见,所以都要调用一次 add()

对象的visible属性也能控制可见性。使用api.setObjectVisible()

remove

把对象从当前场景树中移除,但不会释放其底层资源,使其不可见:

js
await api.remove(image);

意味着视频、动画等还可以继续播放,只是看不见而已。

适合做临时隐藏或重新挂接父子关系。

destroyObject

彻底销毁对象并释放资源:

js
await api.destroyObject(image);

一旦销毁,之前保存的句柄对象就不能继续使用,建议立即移除对象句柄,避免继续引用。

remove 和 destroyObject 的区别

方法是否从场景消失是否释放资源是否还能再次 add
remove()
destroyObject()不能

如果你后面还打算继续使用这个对象,优先 remove();如果已经确定不会使用,则用 destroyObject()

clear

清空并销毁当前场景的所有对象

js
await api.clear();

一般情况下不使用,非常危险的操作。会导致获取的所有对象句柄都失效。

如果只想销毁动态创建出来的对象,则需要用户自己储存对象列表,并在需要销毁时,再进行remove/destroyObject。

一个简单的宿主层封装

js
let dynamicObjects = [];

async function addObject(handle) {
  await api.add(handle);
  dynamicObjects.push(handle);
}

async function removeObject(handle) {
  await api.remove(handle);
  dynamicObjects = dynamicObjects.filter(o => o !== handle);
}

async function destroyAllDynamicObjects() {
  while (dynamicObjects.length) {
    const handle = dynamicObjects.pop();
    await api.remove(handle);
    await api.destroyObject(handle);
  }
}

推荐清理时机

页面销毁

当宿主页面本身要卸载时:

  1. 先清理你注册过的对象事件
  2. 再销毁动态对象
  3. 最后关闭 iframe

场景切换

如果你是“同一个 iframe 中重复打开不同 sceneId”:

  • 不要复用旧场景中的对象句柄
  • 不要复用旧场景中的高级api对象

父子关系管理

添加子对象

js
const group = await api.createGroup();
const image = await api.createImage(arrayBuffer);

await api.add(group);
// 将image添加到group的子列表中。
// 因为group已在上一步进入场景树,所以image不需要再调用api.add。
await api.addChild(group, image);

任何3D对象,都可以增加子对象。

包括camera、图片、视频、模型等。

音频不属于3D对象,就不能增加。

移除子对象

js
await api.removeChild(group, image);

获取子对象列表

js
const children = await api.getChildren(obj); // 输出Array