关于 hz-iwsdk-webxr
用于使用 Meta Immersive Web SDK(IWSDK)构建 Meta VR WebXR 体验的开发技能,面向 WebXR 开发者。它结合 ECS、Three.js、空间 UI 和 XR 输入,并介绍基于 Vite 的开发与测试流程。
主要功能
- 01使用 ECS 架构组织场景
- 02集成 Three.js 渲染流程
- 03构建空间 UI 面板
- 04处理控制器、手势与指针输入
- 05通过 Vite 开发并测试 WebXR
适用场景
- 01创建面向 Quest Browser 的 WebXR 体验
- 02构建由实体与系统组成的 3D 场景
- 03实现世界空间或屏幕空间 UI
- 04迭代调试头显中的 XR 应用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meta-quest/ agentic-tools --skill hz-iwsdk-webxr安装后在 Claude Code 中输入/hz-iwsdk-webxr确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ai-assisted-development.mddesktop-load-profiling.mdecs-architecture.mdinput-handling.mdperformance-tips.mdspatial-ui.md详细介绍
IWSDK WebXR 技能
使用 Meta 的 Immersive Web SDK(IWSDK)为 Meta VR 构建沉浸式 WebXR 体验。本技能涵盖当前的软件包布局、ECS 架构、Three.js 集成、空间 UI 开发、XR 输入处理,以及推荐的基于 Vite 的开发循环。
何时使用本技能
在以下情况下使用本技能:
- 使用 IWSDK 构建面向 Meta VR 的 WebXR 体验
- 使用基于 Three.js 的 ECS 架构创建 3D 场景
- 使用 UIKitML 和
PanelUI设计空间 UI 面板 - 处理来自控制器、手部和世界空间指针的 XR 输入
- 为 IWSDK 应用运行编辑、重新加载、观察和修复的闭环工作流
- 针对 Meta VR 硬件优化 WebXR 性能
- 使用 IWSDK 的 Vite 开发工具和 Quest Browser 调试和测试 WebXR 应用
本技能适用于使用凝视捏合输入的 Meta VR 眼镜,以及所有使用 Quest Browser 的 Meta Quest 头显。
什么是 IWSDK
Immersive Web SDK(IWSDK)是 Meta 用于构建 WebXR 体验的框架。它提供:
- 实体组件系统(ECS):一种以数据为导向的架构,基于类型化组件存储和查询驱动的系统构建
- Three.js 集成:IWSDK 管理渲染器、场景、摄像机和 XR 会话生命周期,让应用代码可以专注于内容
- 空间 UI 工具包:UIKitML 以及
PanelUI、PanelDocument和UIKitDocument,用于世界空间和屏幕空间 UI - XR 输入管理:统一处理控制器、手部追踪、指针和抓取
- 移动和交互系统:可选择启用抓取、传送、滑动和转向功能
- 资源管理:基于清单的预加载,以及通过
AssetManager按键访问
IWSDK 通过 WebXR Device API 在浏览器中运行。应用是标准网页,开发期间通常由 Vite 提供服务,并在 Quest Browser 中打开以进行设备端验证。
当前的软件包和工具
这些细节很重要,因为较早的预发布版指南现已不再适用:
- 主要运行时软件包是
@iwsdk/core - 官方脚手架命令是
npm create @iwsdk@latest - 默认开发循环使用
@iwsdk/vite-plugin-dev - 本地 HTTPS 通常由
vite-plugin-mkcert处理 - 当前 IWSDK 软件包要求 Node.js
>=20.19.0 @iwsdk/core重新导出了@iwsdk/xr-input和@iwsdk/locomotor
快速入门
1. 创建新项目
npm create @iwsdk@latest my-project
cd my-project
如果从官方创建流程开始,也可以让它为你安装依赖并初始化 git。
2. 安装依赖
npm install
如果要手动设置,请使用 @iwsdk/core、three、@iwsdk/vite-plugin-dev 和 vite-plugin-mkcert,而不要使用旧版 @meta-quest/iwsdk 软件包。
3. 启动开发服务器
npm run dev
标准的 IWSDK Vite 设置会提供安全的本地开发服务器、热模块替换,以及通过 @iwsdk/vite-plugin-dev 实现的模拟器/开发浏览器工作流。
4. 在 XR 中测试
通常有两种验证方式:
- Quest Browser:在头显上打开安全的开发 URL,并在那里启动 XR
- IWSDK 开发工具:使用 Vite 插件的模拟器/开发浏览器路径,快速进行桌面端迭代
Quest Browser 测试需要 HTTPS。如果应用在桌面端可以运行,但在设备上无法进入 XR,请确认开发服务器 URL 安全且头显可以访问。如果仍无法进入 XR,头显上的 metavr log 通常会指出未通过的检查项(HTTPS、WebXR 标志、GPU 进程)。
AI 辅助开发循环
IWSDK 非常适合编码 Agent,因为它的开发循环本身就是面向 Web 的:编辑源代码、重新加载页面、观察行为并迭代。
推荐的开发循环:
- 编码前,先根据当前文档核实 API 和平台细节
- 编辑代码并运行 Vite 开发服务器
- 在 Quest Browser 或 IWSDK 模拟器/开发浏览器中重新加载页面
- 查看日志、屏幕截图和运行时状态
- 持续迭代,直到运行时行为符合要求
如果你将原生 Meta VR 前端与主机端编码 Agent 配合使用,请保持前端精简。由主机负责管理代码仓库、文件编辑、依赖安装、测试、构建步骤和 metavr 工具调用。
项目结构
典型的 IWSDK 项目如下所示:
my-project/
src/
index.ts # Entry point: World.create, scene setup, XR controls
systems/ # Optional ECS systems
movement.ts
components/ # Optional ECS components
velocity.ts
public/
models/ # GLTF / GLB assets
textures/ # Textures and images
audio/ # Audio assets
ui/ # Compiled UIKitML JSON output
ui/
welcome.uikitml # Source UIKitML files
vite.config.ts
package.json
tsconfig.json
关键模式
创建组件
import { Types, createComponent } from '@iwsdk/core';
export const Velocity = createComponent(
'Velocity',
{
x: { type: Types.Float32, default: 0 },
y: { type: Types.Float32, default: 0 },
z: { type: Types.Float32, default: 0 },
},
'Linear velocity in meters per second',
);
编写系统
import { createSystem } from '@iwsdk/core';
import { Velocity } from './components/velocity';
export class MovementSystem extends createSystem({
moving: { required: [Velocity] },
}) {
update(delta: number) {
this.queries.moving.entities.forEach((entity) => {
if (!entity.object3D) {
return;
}
entity.object3D.position.x += Velocity.data.x[entity.index] * delta;
entity.object3D.position.y += Velocity.data.y[entity.index] * delta;
entity.object3D.position.z += Velocity.data.z[entity.index] * delta;
});
}
}
使用 Three.js 网格生成实体
import * as THREE from 'three';
import { Velocity } from './components/velocity';
function spawnCube(world) {
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(0.5, 0.5, 0.5),
new THREE.MeshStandardMaterial({ color: 0x00aaff }),
);
const entity = world.createTransformEntity(mesh);
entity.object3D!.position.set(0, 1.5, -2);
entity.addComponent(Velocity, { x: 0, y: 0, z: 0 });
}
创建世界并启动 XR
import {
ReferenceSpaceType,
SessionMode,
World,
} from '@iwsdk/core';
const container = document.getElementById('scene-container') as HTMLDivElement;
const world = await World.create(container, {
xr: {
sessionMode: SessionMode.ImmersiveVR,
referenceSpace: ReferenceSpaceType.LocalFloor,
offer: 'none',
},
});
world.registerSystem(MovementSystem);
world.launchXR();
World.create(...) 已经配置好渲染器、核心系统、资源加载和渲染循环。不要教 Agent 使用 new World()、createWorld()、world.start() 或较旧的 enterXR(...) 路径。
易踩坑
以下是在为 Meta VR 构建 IWSDK WebXR 应用时,可能导致意外失败或浪费调试时间的常见问题。
- 设备上的 WebXR 需要 HTTPS —— WebXR Device API 仅支持通过 HTTPS(或 localhost)使用。如果你通过普通 HTTP 提供开发构建版本,并在 Quest Browser 中打开,便不会显示“进入 VR”按钮。开发期间可使用
ngrok、自签名证书或 Vite 的--https标志建立 HTTPS 隧道。 - Quest Browser 是 Chromium,而不是桌面版 Chrome —— 功能支持存在差异。
SharedArrayBuffer、某些 WebGL2 扩展和OffscreenCanvas的表现可能不同,也可能不可用。务必在实际的 Quest Browser 上测试,而不仅是在带有 IWER 模拟器的桌面版 Chrome 上测试。 - 默认刷新率为 72 Hz,而不是 90 Hz —— Quest Browser 中的 WebXR 会话默认以 72 Hz 运行。会话启动后,必须通过
xrSession.updateTargetFrameRate(90)明确请求更高的帧率。忘记这一步,是 WebXR 应用相比原生构建版本感觉“迟钝”的最常见原因。 - 绘制调用预算远低于原生应用 —— Quest 2 上应将绘制调用控制在 50-80 次以下,Quest 3 上则控制在 100-120 次以下。每次绘制调用带来的 JavaScript 开销高于原生应用。应批量处理几何体、使用实例化渲染,并尽可能合并材质。
- 纹理内存限制 —— Quest Browser 的 GPU 内存上限低于原生应用。大型未压缩纹理(4K 及以上)可能导致无提示的 OOM 崩溃或画面损坏。请使用压缩纹理(采用 Basis Universal 或 ETC2 的 KTX2),并将纹理总内存控制在 256 MB 以下。
requestAnimationFrame与 XR 帧循环 —— XR 会话启动后,必须使用xrSession.requestAnimationFrame,而非window.requestAnimationFrame。使用错误的接口会导致场景冻结或以错误的速率渲染。- 手部追踪捏合阈值 —— WebXR 手部追踪 API 会将捏合报告为连续值(0.0-1.0)。许多开发者会将阈值设为 0.5,但在 Meta VR 设备上,可靠的激活阈值更接近 0.7-0.8。较低的阈值会导致误触,尤其是在做指向手势时。
- HMR 可能会破坏 XR 会话 —— 热模块替换有时无法正确拆除并重新创建 WebXR 会话。如果 HMR 更新后场景变黑,请完整重新加载页面,不要浪费时间排查并不存在的渲染问题。
- CORS 会阻止 VR 中的资源加载 —— 从 CDN 加载 GLTF/GLB 模型或纹理时,请确保设置了正确的 CORS 标头。Quest Browser 会严格执行 CORS 策略。缺少标头会导致资源加载无提示地失败;如果没有连接 DevTools,就很难诊断。
- 对于仅包含 canvas 的 WebXR 页面,Lighthouse 无法生成依赖 LCP 的结果 ——
<canvas>永远不会成为 LCP 候选项,因此 Lighthouse 的largest-contentful-paint、interactive/TTI 和total-blocking-time审计会因LanternError: NO_LCP而中止。请根据 CDP 长任务和网络数据自行计算 TTI,并使用硬件 ANGLE 后端启动无头 Chromium(Windows 上使用--use-angle=d3d11,Linux 上使用--use-angle=gl),否则它会在不提示的情况下以 SwiftShader 软件光栅器进行分析,测得的帧耗时是实际值的 10 倍。请参阅桌面端加载分析。
开发技巧
- 使用
World.create(...)、world.launchXR()和world.exitXR()作为 运行时控制接口 - 在 Quest Browser 开发期间保持启用 HTTPS,因为 WebXR 仅允许在安全上下文中运行
- 从
@iwsdk/vite-plugin-dev和 Quest Browser 验证入手,然后再加入模拟器/开发浏览器工作流以加快迭代 - 针对尚未近期验证过的 API 进行编码前,先搜索并查阅 Meta 文档
- 尽早并频繁地在真实的 Meta VR 设备上测试,因为桌面模拟无法覆盖所有输入、舒适度和性能问题
- 控制绘制调用数量(大致低于 100 次),以确保 Meta VR 硬件上的流畅性能