如何在 xr-frame 執行階段載入 AR 場景下的 3D 內容
本文詳細闡述了 xr-frame 資源載入與節點掛載的分離機制,透過腳本動態實現 3D 內容在 Block 節點下的靈活掛載,實現 AR。
官方資料
- xr-frame 開發指南:微信官方 XR 引擎文件。
- xr-frame 官方範例:包含各類基礎與進階用法示例。
官方資料中已經有充分的內容說明如何在執行階段載入 3D 內容,本文中僅簡要說明一些 AR 場景下常用的內容和載入方式。
資源載入 vs 節點掛載
在 xr-frame 中,顯示一個 3D 模型分為兩個階段:
資源載入:指將模型檔案(如
.glb)從網路或本地下載並解析到記憶體中。此時模型已就緒,但在場景中不可見。節點掛載:指在場景樹中建立一個節點,並將已載入的資源關聯到該節點上。此時模型才會正式出現在渲染畫布中。
如何使用程式碼動態載入 3D 內容
資源載入
透過 xr-frame 場景的資源管理系統呼叫 loadAsset手動載入資源。
參數中的
type指資源類型,assetId指載入後的資源 id,src指資源的 url,一般是資源託管伺服器的位址。需要記錄
assetId用於後續的掛載和釋放資源。try { await scene.assets.loadAsset({type: 'gltf', assetId: 'panda', src: 'url/EasyARPanda.glb'}); } catch (err) { console.error(`Failed to load assets: ${err.message}`); }節點掛載
使用
element.addChild()將載入好的模型放在 ShadowRoot 下。const root = scene.getElementById("shadow-root"); let panda = scene.createElement(xrFrameSystem.XRGLTF, { "model": "panda", "anim-autoplay": "" } ); root.addChild(panda);ShadowRoot 元素是 xr-frame 專門用來防止動態建立和移除節點的根節點,詳見 Shadow節點。
使用插件物件提供的 createXRNodeFromNodeAnnotation 方法能夠根據 EMA 資料建立 Block 的子節點,確保 3D 內容顯示在正確的空間位置。
const nodeAnnotation = annotation as easyar.ema.v0_5.Node; const xrNode: xrfs.XRNode = easyarPlugin.createXRNodeFromNodeAnnotation(nodeAnnotation, blockHolder); let panda = scene.createElement(xrFrameSystem.XRGLTF, { "model": "panda", "anim-autoplay": "" } ); xrNode.addChild(panda);
如何在 Block 下不使用標註直接掛載內容
透過 getBlockById(id) 取得場景樹上的 block 節點物件,如果不存在相應的 block 節點說明對這個 Block 的定位還未成功過(在第一次定位到該 Block 時節點會被自動建立)。可以用 holdBlock(blockInfo, blockTransformInput) 建立一個該 Block 的節點,也可以在定位回呼中判斷對該 Block 的定位成功再掛載內容。
提示
在 Unity 編輯器的場景樹中選擇 Block 節點 記錄它 Inspector 面板上顯示的 ID

也可以在雲定位庫頁面中查到 Block ID

const blockID = "aaaa1234-bbbb-cccc-dddd-eeeeee123456"
if (!blockHolder.getBlockById(blockParent.id)) {
// 沒有存在的 Block 節點,建立一個
blockHolder.holdBlock({
id: blockID
})
}
let blockElement = blockHolder.getBlockById(blockParent.id).el;
將模型節點以掛載到指定的 Block 下,分別用 position.setArray(),quaternion.set() 和 scale.setArray() 把修改模型節點的 LocalTransform 。
export interface LocalTransform {
/** @description 位置 */
position: xrfs.Vector3;
/** @description 旋轉 */
rotation: xrfs.Quaternion;
/** @description Scale */
scale: xrfs.Vector3;
}
// 假設有一個已知的在 Block 下的 LocalTransform
const targetTransform: LocalTransform;
blockElement.addChild(modelNode);
let modelTransform = modelNode.getComponent(xrFrameSystem.Transform);
modelTransform.position.setArray([
targetTransform.position.x,
targetTransform.position.y,
targetTransform.position.z
]);
let annoRotation = new xrFrameSystem.Quaternion().setValue(
targetTransform.rotation.x,
targetTransform.rotation.y,
targetTransform.rotation.z,
targetTransform.rotation.w
);
modelTransform.quaternion.set(annoRotation);
modelTransform.scale.setArray([
targetTransform.scale.x,
targetTransform.scale.y,
targetTransform.scale.z
]);
xr-frame 支援的資源類型
- Texture 紋理和影像
- CubeTexture 立方體紋理
- VideoTexture 影片紋理
- EnvData 環境
- GLTF 模型
- Keyframe 幀動畫
- Atlas 圖集
每種資源的載入方法詳細見微信官方文件及 xr-frame 官方範例
附註
支援的 GLTF 格式及拓展參考 xr-frame 官方 GLTF 使用說明