Tiny World WebXR 是一套面向 Tiny World Builder 的 WebXR 集成技能,用于在项目中添加或修改 WebXR 能力、AR 放置、VR 沉浸、头显控制器输入以及 XR 渲染模式。
一、用途与平台划分 该技能强调把 WebXR 集成保持为原生、单文件的形式,写在 tiny-world-builder.html 内,并使用固定的全局 THREE r185 兼容包(vendor/three/tinyworld-three.r185.min.js),不使用运行时模块导入或 ARButton/VRButton 插件。平台方面,WebXR 覆盖 Android Chrome / Quest 上的 Google AR(通过 immersive-ar 加 hit-test 实现),但 Apple 设备不支持 WebXR;iOS/iPadOS 的网页 AR 只能走 AR Quick Look:一个指向 .usdz 文件的 <a rel="ar"> 链接会打开系统查看器,由系统查找平面、放置模型并允许用户环绕查看。因此两条路径需要并存才能完整覆盖。
二、Apple AR 的实现要点 针对 Apple AR,技能建议按需用 r185 全局包中的 THREE.USDZExporter 把当前世界导出为 USDZ。由于 USDZExporter 只识别 MeshStandardMaterial,需要先把 worldGroup 快照到一个新组中,将每个 Lambert/Basic/Shader 材质转换为 Standard 等价材质(保留颜色、自发光和贴图),再以原点为中心重新居中、让底部位于 y=0,并缩放到桌面尺寸。随后把得到的 Uint8Array 包装为 model/vnd.usdz+zip Blob 生成对象 URL,通过一个仅包含单个 <img> 子元素的 <a rel="ar">(Safari 的要求)以程序化方式点击启动。
三、按钮显示与渲染循环 Apple AR 按钮通过 document.createElement('a').relList.supports('ar') 判断是否显示,WebXR 按钮则依据 navigator.xr 支持情况显示;只要两者之一可用就显示 XR 面板,这样 iOS 用户只会看到 Apple AR 按钮。启用 WebXR 需要设置 renderer.xr.enabled = true,并用 renderer.setAnimationLoop(animate) 驱动主循环,使桌面和头显帧共用同一路径。
四、场景结构与坐标系 头显变换应放在 xrWorldRoot 上,它是棋盘/运行时网格的场景级父节点;不要单独缩放或移动 worldGroup,因为悬停、选择、云、天气、烟雾、作物喷粉机和预览都必须保持在同一个局部世界空间。控制器和准星应留在 scene 中,而不是 xrWorldRoot,它们属于物理 XR 空间对象。
五、XR 模式与会话参数 AR 桌面模式请求 immersive-ar,需要 hit-test,可选 anchors 和 domOverlay 根节点;用准星姿态设置 xrWorldRoot,有 anchors 时使用,但可平滑回退到最近一次 hit-test 姿态。浮动模式优先 immersive-ar,失败则回退 immersive-vr,并把迷你棋盘放在当前 XR 相机前方。室内模式使用带 local-floor 的 immersive-vr,xrWorldRoot 保持米级比例(scale = 1),使一个地块达到可步入的房间尺度。
六、拾取与状态恢复 用控制器拾取地块时,对 worldGroup.children 做射线检测,然后通过 xrWorldRoot.worldToLocal() 转换 h.point,再计算地块局部偏移;桌面指针拾取可继续使用屏幕空间射线。XR 会话结束或失败时,需要恢复 scene.background、xrWorldRoot 的变换与可见性、准星状态和 UI 状态。
七、验证与限制 验证要求 npm test 和行内脚本的 node --check 通过。真实 AR hit-test 或 VR 进入需要 HTTPS 以及支持 WebXR 的头显/浏览器;浏览器冒烟测试只能验证非 XR 回退 UI 和语法。