鸿蒙开发-想管理AR场景?arViewController场景管理详解
摘要: arViewController是AR应用的核心管理模块,负责AR会话的全生命周期管理。它通过ARViewContext对象提供AR能力配置、会话初始化、3D场景设置等功能。开发者需配置AR类型(如环境追踪、人体识别等)、坐标系模式、功耗模式等参数后调用init()初始化。该模块支持动态加载3D场景,并提供了会话状态管理和错误处理机制。使用前需确保设备兼容性和摄像头等权限,初始化失败时会返
想管理 AR 场景?arViewController 场景管理详解
你有没有想过,一个完整的 AR 应用到底是怎么运作的?从打开摄像头、初始化 AR 引擎、配置各种追踪能力,到暂停恢复、销毁资源——这一整套流程靠什么来管理?
答案就是 arViewController。它是 AR Engine 的"大管家",负责 AR 会话的创建、配置、生命周期管理,以及 3D 场景的设置。你可以把它理解为 AR 应用的"控制器"——所有的 AR 能力都要通过它来启动和管理。
arViewController 包含什么?
下面是 AR 应用的完整生命周期流程:
arViewController 模块主要提供两个核心东西:
ARViewContext:AR 视图上下文,是整个 AR 应用的核心对象。它管理着 AR 会话、3D 场景、回调、配置等一切东西。ARViewCallback:AR 视图的回调抽象类,你需要继承它来实现自己的回调逻辑。
使用之前,先导入模块:
import { arEngine, arViewController } from '@kit.AREngine';
注意,arViewController 和 arEngine 是从同一个包 @kit.AREngine 导入的。arEngine 提供各种 AR 数据类型和枚举,arViewController 提供场景管理能力。
怎么创建 ARViewContext?
创建 ARViewContext 非常简单,就一行代码:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
ARViewContext 是整个 AR 应用的核心对象。你需要通过它来:
- 配置 AR 会话的参数
- 初始化和管理 AR 会话的生命周期
- 设置 3D 场景
- 注册回调函数
- 管理虚拟模型的放置和移除
怎么配置 AR 能力?
下面是 AR 能力配置的决策流程:
创建好 ARViewContext 之后,你需要告诉它你要用哪些 AR 能力。通过 config 属性来设置:
import { arEngine, arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.config = {
type: arEngine.ARType.WORLD,
poseMode: arEngine.ARPoseMode.GRAVITY_AND_HEADING,
powerMode: arEngine.ARPowerMode.POWER_SAVING,
depthMode: arEngine.ARDepthMode.AUTOMATIC
};
config 接受一个 arEngine.ARConfig 对象,里面包含了 AR 会话的所有配置参数。我把常用的配置项整理一下:
type(ARType):AR 能力类型,这是最重要的配置。
WORLD(0x01):环境追踪能力,也就是 SLAM。用于平面检测、运动跟踪等。BODY(0x02):人体跟踪与骨骼关键点识别能力。FACE(0x10):人脸追踪能力。IMAGE(0x80):图像识别能力。
这些类型是按位组合的,理论上你可以同时开启多个能力。但要注意,同时开启的能力越多,消耗的资源就越多。
planeFindingMode(ARPlaneFindingMode):平面检测模式。默认是 HORIZONTAL_AND_VERTICAL,同时检测水平面和竖直平面。
poseMode(ARPoseMode):世界坐标系的建立方式。默认是 GRAVITY(Y 轴跟重力对齐)。如果你想加上指南针方向,可以用 GRAVITY_AND_HEADING。
powerMode(ARPowerMode):电源功耗模式。默认是 NORMAL。如果手机发热严重,可以换成 POWER_SAVING。
focusMode(ARFocusMode):对焦模式。默认是 FIXED(固定焦点)。
depthMode(ARDepthMode):深度模式。默认是 DISABLED。如果需要深度信息,设成 AUTOMATIC。
meshMode(ARMeshMode):网格模式。默认是 DISABLED。如果需要 Mesh 数据,设成 ENABLE。
maxMapSize:存储地图数据的最大内存大小,单位是 MB。可设定范围 100MB ~ 16GB,默认 800MB。建议根据设备的内存容量来设置,太大会导致意外错误。
cameraLensFacing:相机镜头朝向。默认是 REAR(后置摄像头)。如果要做自拍特效,设成 FRONT。注意,当设为 FRONT 时,type 必须是 FACE 或 BODY 才会生效。
maxDetectedBodyNum:当类型为 BODY 时,要检测的人体数量最大值。默认是 1,最大是 2。
配置要在 init() 之前设置好。初始化之后再改配置可能不会生效。
怎么初始化 AR 会话?
配置好之后,调用 init() 来初始化 AR 会话:
import { arViewController } from '@kit.AREngine';
import { BusinessError } from '@kit.BasicServicesKit';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
await context.init();
init() 是一个异步方法,返回 Promise<void>。调用之后,AR Engine 会:
- 检查权限(需要
CAMERA、GYROSCOPE、ACCELEROMETER三个权限) - 检查设备兼容性
- 启动摄像头
- 初始化传感器
- 创建 AR 会话
- 设置 3D 渲染场景
- 开始追踪
初始化过程中可能会失败,常见的错误码有:
- 201:权限未授予。你需要确保应用有摄像头、陀螺仪和加速度计的权限。
- 801:设备不兼容。这个设备不支持 AR 能力。
- 1009200007:配置不支持。你设置的某些配置参数在当前设备上不可用。
- 1009200010:摄像头不可用。可能被其他应用占用了。
所以最好用 try-catch 来处理初始化失败的情况。
怎么设置 3D 场景?
AR 应用通常需要在现实画面上叠加 3D 虚拟内容。这就需要一个 3D 渲染场景。通过 scene 属性来设置:
import { Scene } from '@kit.ArkGraphics3D';
import { arViewController } from '@kit.AREngine';
Scene.load().then((scene: Scene) => {
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.scene = scene;
}).catch((err: BusinessError) => {
console.error(`Failed to load scene. Code is ${err.code}, message is ${err.message}.`);
});
这里先用 Scene.load() 加载一个 3D 场景,然后把它赋值给 context.scene。Scene 是 @kit.ArkGraphics3D 提供的 3D 场景管理类。
你也可以反过来,获取当前设置的场景:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.scene;
scene 属性既是 getter 也是 setter,你可以随时读取或修改当前的 3D 场景。
怎么获取 AR 会话?
初始化成功后,你可以通过 session 属性获取底层的 AR 会话对象:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.session;
session 返回的是 arEngine.ARSession 对象。如果初始化成功,返回 ARSession 实例;如果初始化失败或还没初始化,返回 undefined。
拿到 ARSession 之后,你就可以使用 AR Engine 的底层能力了,比如:
getFrame():获取当前帧数据getAllTrackables():获取所有可追踪对象createAnchor():创建锚点
打个比方,ARViewContext 是"总经理",ARSession 是"技术总监"。总经理负责整体管理,技术总监负责具体的技术活。
怎么注册回调?
AR 应用需要对各种事件做出响应——新平面被检测到、平面更新、每一帧刷新。这些都通过回调来处理。
你需要继承 ARViewCallback 类,实现自己的回调逻辑:
import { arEngine, arViewController } from '@kit.AREngine';
import { Node } from '@kit.ArkGraphics3D';
class ARViewCallbackImpl extends arViewController.ARViewCallback {
onAnchorAdd(ctx: arViewController.ARViewContext, node: Node, anchor: arEngine.ARAnchor): void {
console.info('onAnchorAdd');
console.info(`add anchor id = ${String(anchor.id)}`);
console.info(`add anchor translation = ${anchor.getPose().translation}`);
console.info(`add node pose = ${node.position}`);
}
onAnchorUpdate(ctx: arViewController.ARViewContext, node: Node, anchor: arEngine.ARAnchor): void {
console.info('onAnchorUpdate');
console.info(`update anchor id = ${String(anchor.id)}`);
console.info(`update anchor translation = ${anchor.getPose().translation}`);
console.info(`update node pose = ${node.position}`);
}
async onFrameUpdate(ctx: arViewController.ARViewContext, sysBootTs: number): Promise<void> {
let arSession: arEngine.ARSession | undefined = ctx.session;
if (arSession) {
let frame: arEngine.ARFrame = arSession.getFrame();
if (!frame) {
console.error('Failed to get arSession.frame, it is undefined or null');
} else {
console.info(`Succeeded in getting arSession.frame = ${frame.timestamp}`);
await frame.release();
}
} else {
console.error('Failed to get arSession, arSession is undefined');
}
}
}
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.callback = new ARViewCallbackImpl();
然后通过 context.callback 把回调实例注册进去。
三个回调方法的作用:
onAnchorAdd(ctx, node, anchor):当 AR 会话检测到新平面(或其他可追踪对象)时触发。AR Engine 会自动创建锚点和对应的场景节点,然后通过这个回调通知你。参数说明:
ctx:当前 ARView 的上下文信息node:新建锚点对应的 AR 场景节点anchor:新创建的锚点
onAnchorUpdate(ctx, node, anchor):当已有锚点更新时触发。参数跟 onAnchorAdd 一样。
onFrameUpdate(ctx, sysBootTs):每帧刷新前触发。sysBootTs 是系统启动时间戳,单位是微秒。你可以在这里获取当前帧的 AR 数据,做实时渲染和逻辑处理。
生命周期管理:暂停、恢复和销毁
AR 应用不是一直运行的。用户切到后台、锁屏、或者退出 AR 页面时,你需要暂停或销毁 AR 会话来节省资源。
暂停:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.pause();
pause() 会暂停相机跟踪与 AR 场景渲染。调用之后,AR Engine 不再消耗 CPU/GPU 资源来做追踪计算,但 AR 会话本身还保持着。用户回到 AR 页面时,可以快速恢复。
恢复:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.resume();
resume() 会恢复之前暂停的相机跟踪和 AR 场景渲染。调用之后,AR Engine 继续工作。
销毁:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.destroy();
destroy() 会销毁 ARViewContext,释放所有资源,包括 AR 会话和 3D 场景。这个方法是异步的,返回 Promise<void>。在退出 AR 页面时调用,确保不会泄露资源。
一个典型的 AR 页面生命周期是这样的:
- 页面创建:
new ARViewContext()→ 设置config→init()→ 设置scene→ 设置callback - 用户切到后台:
pause() - 用户回到前台:
resume() - 用户退出页面:
destroy()
坐标系转换
AR Engine 用的是重力对齐世界坐标系,而 3D 渲染引擎(AGP)用的是自己的世界坐标系。两个坐标系不一样,所以在 3D 场景里放虚拟物体时,需要做一次坐标转换。
ARViewContext 提供了 transformPose() 方法来帮你做这个事情:
import { arViewController } from '@kit.AREngine';
import { Vec3, Quaternion } from '@kit.ArkGraphics3D';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
let pose: Vec3 = { x: 1.0, y: -1.0, z: -0.5 };
let rot: Quaternion = {
x: -0.1,
y: 0.2,
z: -0.3,
w: 0.5
};
context.transformPose(pose, rot);
transformPose(position, rotation) 接收两个参数:
position(Vec3):位姿坐标信息rotation(Quaternion):位姿朝向信息(四元数)
返回的是转换后的 arEngine.ARPose 对象,如果参数无效或创建失败,返回 null。
打个比方,你在 AR 坐标系中检测到了一个平面,它的位姿是 (1.0, -1.0, -0.5)。你想在 3D 场景里对应的位置放一个虚拟物体,就需要先用 transformPose 把这个位姿从 AR 坐标系转换到 AGP 渲染坐标系,然后再设置虚拟物体的位置。
设备兼容性检查
不是所有设备都支持 AR 能力。在使用之前,你可以用 isARTypeSupported() 来检查:
import { arEngine, arViewController } from '@kit.AREngine';
arViewController.isARTypeSupported(arEngine.ARFeatureType.ARENGINE_FEATURE_TYPE_FACE);
这个方法返回 boolean,true 表示支持,false 表示不支持。
你可以检查不同的特性类型:
ARENGINE_FEATURE_TYPE_FACE:人脸识别与跟踪特性ARENGINE_FEATURE_TYPE_BODY:人体骨骼点识别与跟踪特性- 还有其他更多特性类型
这个检查很重要,因为不同设备的硬件能力不同。比如有些低端设备可能不支持人体骨骼追踪,强行使用会报 801(Device not compatible)错误。
管理虚拟模型
ARViewContext 还提供了管理虚拟模型的方法。你可以在人脸关键点位置放置、移除和清除 3D 模型:
放置模型:
import { arEngine, arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
// 此处为用户本地存放模型路径
let resourcePath:ResourceStr = $rawfile('xxxx/xxxx');
context.loadAsset(resourcePath, arViewController.LandmarkType.LEFT_EYE);
loadAsset(resourcePath, landmark) 在指定的关键点处放置一个 3D 模型。resourcePath 是模型文件的路径,landmark 是关键点类型。
移除模型:
import { arEngine, arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.removeAsset(arViewController.LandmarkType.LEFT_EYE);
removeAsset(landmark) 移除指定关键点上已放置的模型。
清除所有模型:
import { arViewController } from '@kit.AREngine';
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
context.clearResource();
clearResource() 一次性清除所有已放置的模型。这个方法是异步的,返回 Promise<void>。
错误码速查
在使用 arViewController 的过程中,可能会遇到各种错误。把常见的错误码整理一下:
| 错误码 | 含义 | 常见原因 |
|---|---|---|
| 201 | 权限未授予 | 缺少摄像头、陀螺仪或加速度计权限 |
| 801 | 设备不兼容 | 设备不支持 AR 能力 |
| 401 | 参数无效 | 传入的参数不合法 |
| 1009200001 | 通用失败 | AR Engine 内部错误 |
| 1009200007 | 配置不支持 | 设置了设备不支持的配置参数 |
| 1009200008 | 资源耗尽 | 内存不足或资源被占满 |
| 1009200009 | 服务不可用 | AR 服务未启动或崩溃 |
| 1009200010 | 摄像头不可用 | 摄像头被其他应用占用 |
| 1009200201 | ARView 无效操作 | 在错误的状态下调用了 API |
| 1009200202 | 需要 3D AR 场景 | 没有设置 scene 就调用了需要场景的方法 |
| 1009200203 | 需要 AR 配置 | 没有设置 config 就初始化 |
| 1009200204 | AR 会话设置失败 | 初始化过程中出错 |
| 1009200205 | AR 场景相机设置失败 | 3D 场景的相机初始化失败 |
遇到错误时,先看错误码,再对照这个表排查原因。大部分问题都是权限、设备兼容性或配置参数导致的。
一个完整的 AR 应用流程
最后把整个流程串起来:
import { arEngine, arViewController } from '@kit.AREngine';
import { Scene } from '@kit.ArkGraphics3D';
import { Node } from '@kit.ArkGraphics3D';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建 ARViewContext
let context: arViewController.ARViewContext = new arViewController.ARViewContext();
// 2. 配置 AR 能力
context.config = {
type: arEngine.ARType.WORLD,
planeFindingMode: arEngine.ARPlaneFindingMode.HORIZONTAL_AND_VERTICAL,
poseMode: arEngine.ARPoseMode.GRAVITY_AND_HEADING,
powerMode: arEngine.ARPowerMode.POWER_SAVING,
depthMode: arEngine.ARDepthMode.AUTOMATIC
};
// 3. 注册回调
context.callback = new ARViewCallbackImpl();
// 4. 加载 3D 场景
Scene.load().then((scene: Scene) => {
context.scene = scene;
}).catch((err: BusinessError) => {
console.error(`Failed to load scene. Code is ${err.code}, message is ${err.message}.`);
});
// 5. 初始化 AR 会话
await context.init();
// 6. 暂停(用户切到后台时)
context.pause();
// 7. 恢复(用户回到前台时)
context.resume();
// 8. 销毁(退出 AR 页面时)
await context.destroy();
这就是一个完整的 AR 应用生命周期。从创建、配置、初始化,到暂停恢复、销毁,每一步都有对应的 API。
arViewController 是 AR Engine 的入口。掌握了它,你就掌握了 AR 应用的整体框架。至于具体的 AR 能力(平面检测、人体追踪、人脸追踪等),都是在这个框架之上运行的。
更多推荐

所有评论(0)