关于 hz-unity-meta-mixed-reality-utility-kit
hz-unity-meta-mixed-reality-utility-kit 是面向使用 Meta MR Utility Kit 构建场景感知混合现实体验的 Unity 技能参考。内容涵盖场景数据、空间查询、表面放置、房间几何与可追踪对象,并列出 API 入口和包配置细节。
主要功能
- 01从设备或文件加载场景数据
- 02查询房间几何与表面
- 03在场景锚点上生成预制件
- 04根据房间几何生成 NavMesh
- 05访问透视摄像头与可追踪对象
适用场景
- 01在检测到的真实表面放置内容
- 02为 MR 交互查询房间几何
- 03根据扫描房间构建导航
- 04追踪键盘或 QR 码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ meta-quest/ agentic-tools --skill hz-unity-meta-mixed-reality-utility-kit安装后在 Claude Code 中输入/hz-unity-meta-mixed-reality-utility-kit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/passthrough-relighting.mdscene-navigation.mdunity-mcp-fallback.md详细介绍
Meta XR 混合现实实用工具包(MR Utility Kit,MRUK,com.meta.xr.mrutilitykit)
Meta XR 混合现实实用工具包(MR Utility Kit,MRUK)是一个 Unity 软件包,基于 Scene API 提供高级工具,用于构建具备场景感知能力的混合现实(MR)体验。它旨在与 Meta XR Core SDK 搭配使用。 它可处理场景数据的加载和查询、在真实世界表面上生成预制件、通过世界锁定防止锚点漂移、使用环境射线检测实现无需扫描的即时放置、访问透视摄像头、根据房间几何体生成 NavMesh,以及检测可追踪对象(键盘、QR 码)。
软件包:com.meta.xr.mrutilitykit
查找 SDK 源码
软件包 com.meta.xr.mrutilitykit 的位置可能因项目设置而异:
Library/PackageCache/com.meta.xr.mrutilitykit@<hash>/(从注册表缓存)Packages/com.meta.xr.mrutilitykit/(本地软件包引用)- 自定义磁盘路径(嵌入式或本地文件夹)
搜索 SDK 源码前,请先定位软件包根目录:按已知文件名模式搜索文件:
**/com.meta.xr.mrutilitykit*/Core/Scripts/MRUK.cs
然后在后续所有搜索操作中使用解析出的父路径。
快速参考
| 任务 | 类 / 组件 | 源文件 | 关键入口点 |
|---|---|---|---|
| 从设备加载场景 | MRUK | Scripts/MRUK.cs | LoadSceneFromDevice() |
| 从预制件 / JSON 加载场景 | MRUK | Scripts/MRUK.cs | LoadSceneFromPrefab()、LoadSceneFromJsonString() |
| 获取当前房间 | MRUK | Scripts/MRUK.cs | GetCurrentRoom() |
| 防止锚点漂移 | MRUK | Scripts/MRUK.cs | EnableWorldLock = true |
| 查询房间几何体 | MRUKRoom | Scripts/MRUKRoom.cs | Raycast()、IsPositionInRoom() |
| 查找表面 / 最近点 | MRUKRoom | Scripts/MRUKRoom.cs | TryGetClosestSurfacePosition()、GenerateRandomPositionOnSurface() |
| 获取锚点属性 | MRUKAnchor | Scripts/MRUKAnchor.cs | Label、PlaneRect、VolumeBounds |
| 在锚点上生成预制件 | AnchorPrefabSpawner | Scripts/AnchorPrefabSpawner.cs | PrefabsToSpawn、SpawnOnStart |
| 查找随机生成位置 | FindSpawnPositions | Scripts/FindSpawnPositions.cs | StartSpawn()、SpawnLocations |
| 27 切片网格缩放 | GridSliceResizer | Scripts/GridSliceResizer.cs | ResizeTo(Vector3) |
| 生成视觉网格 | EffectMesh | Scripts/EffectMesh.cs | CreateMesh()、CutHoles |
| 可破坏的场景几何体 | DestructibleGlobalMeshSpawner | Scripts/DestructibleGlobalMeshSpawner.cs | CreateOnRoomLoaded |
| GPU 距离场纹理 | SpaceMapGPU | Scripts/SpaceMapGPU.cs | GetSpaceMap()、StartSpaceMap() |
| 靠近边界时渐隐 | RoomGuardian | Scripts/RoomGuardian.cs | GuardianDistance、GuardianMaterial |
| 根据场景生成 NavMesh | SceneNavigation | Scripts/SceneNavigation.cs | BuildSceneNavMesh() |
| 深度 API 射线检测 | EnvironmentRaycastManager | Scripts/EnvironmentRaycastManager.cs | Raycast()、PlaceBox() |
| 透视摄像头图像 | PassthroughCameraAccess | Scripts/PassthroughCameraAccess.cs | GetTexture()、GetCameraPose() |
| 跟踪键盘 / QR 码 | MRUKTrackable | Scripts/MRUKTrackable.cs | TrackableType、MarkerPayloadString |
| 即时放置(无需扫描) | PointAndLocate | Scripts/BuildingBlocks/InstantContentPlacement/ | TryLocateSpace() |
| 共享房间(多人游戏) | MRUK | Scripts/MRUK.cs | ShareRoomsAsync()、LoadSceneFromSharedRooms() |
所有源文件路径均相对于软件包根目录(参见上文“查找 SDK 源码”)。
架构
对象层级
MRUK (singleton MonoBehaviour)
└── MRUKRoom (child GameObjects, one per room)
└── MRUKAnchor (children of rooms: walls, floors, furniture, etc.)
MRUK.Instance是核心枢纽。它加载场景数据、管理房间、处理世界锁定,并提供SceneSettings配置。MRUKRoom表示一个物理房间。它提供空间查询(射线检测、位置检查、表面查询),并持有Anchors、WallAnchors、FloorAnchors、CeilingAnchors、GlobalMeshAnchor。MRUKAnchor表示单个场景元素(墙壁、桌子、沙发等)。它具有Label(SceneLabels 标志)、可选的PlaneRect(2D 边界)、VolumeBounds(3D 边界)和PlaneBoundary2D(多边形顶点)。MRUKTrackable扩展MRUKAnchor,用于表示运行时检测到的对象(键盘、二维码)。
原生库
C/C++ 共享库负责处理世界锁定、锚点发现和坐标转换(OpenXR 右手坐标系 ↔ Unity 左手坐标系)。一个隐藏的 MRUKGlobalContext MonoBehaviour(DontDestroyOnLoad)会在每帧更新原生上下文。你无需直接调用这些功能。
组件模式
所有功能组件(AnchorPrefabSpawner、EffectMesh、FindSpawnPositions、SceneNavigation、SpaceMapGPU、RoomGuardian、DestructibleGlobalMeshSpawner)都遵循相同的模式:
SpawnOnStart/CreateOnStart/BuildOnSceneLoaded属性的类型为MRUK.RoomFilter,用于控制自动初始化- 在
Start()中,它们会调用MRUK.Instance.RegisterSceneLoadedCallback(...);如果场景已加载,该回调会立即触发 - 它们还提供手动方法(
CreateMesh()、StartSpawn()、BuildSceneNavMesh()等),用于以编程方式控制
依赖项
- 必需:
com.meta.xr.sdk.core(OVRCameraRig、OVRPlugin、OVRSpatialAnchor、OVRSemanticLabels) com.unity.ai.navigation(用于 SceneNavigation)com.unity.nuget.newtonsoft-json(用于 JSON 场景序列化)
关键枚举
MRUKAnchor.SceneLabels(标志)
FLOOR, CEILING, WALL_FACE, TABLE, COUCH, DOOR_FRAME, WINDOW_FRAME,
OTHER, STORAGE, BED, SCREEN, LAMP, PLANT, WALL_ART, GLOBAL_MESH,
INVISIBLE_WALL_FACE, UNKNOWN, INNER_WALL_FACE
将其用作标志:SceneLabels.TABLE | SceneLabels.COUCH 可匹配桌子或沙发。
MRUKAnchor.ComponentType(标志)
None = 0, Plane = 1, Volume = 2, All = Plane | Volume
锚点可以具有平面几何形状(2D 矩形)、体积几何形状(3D 边界),也可以同时具有两者。
MRUK.SceneDataSource
Device // Load from device Scene API
Prefab // Load from room prefab GameObjects
DeviceWithPrefabFallback // Device first, prefab if no scene data (recommended for dev)
Json // Load from JSON string
DeviceWithJsonFallback // Device first, JSON if no scene data
MRUK.SurfaceType(标志)
FACING_UP = 1 // Floors, table tops
FACING_DOWN = 2 // Ceilings, undersides
VERTICAL = 4 // Walls
MRUK.RoomFilter
None // Don't auto-initialize
CurrentRoomOnly // Only the room the user is in
AllRooms // All loaded rooms
MRUK.SceneModel
V1 // Standard scene model
V2 // High Fidelity: multiple floors/ceilings, slanted ceilings, inner walls
V2FallbackV1 // Try V2, fall back to V1 if unsupported
LabelFilter
用于按标签和组件类型筛选锚点的结构体。用于射线检测、表面查询和生成方法。
var filter = new LabelFilter(SceneLabels.TABLE | SceneLabels.COUCH, ComponentType.Volume);
bool passes = filter.PassesFilter(anchor.Label);
MRUK.PositioningMethod
DEFAULT // Standard positioning
CENTER // Center of surface (e.g., center of table for chess board)
EDGE // Edge of surface (e.g., edge of table for piano)
核心类
MRUK(单例)
关键属性:Instance(静态)、IsInitialized、Rooms(List<MRUKRoom>)、EnableWorldLock、IsWorldLockActive、TrackingSpaceOffset、SceneSettings
关键方法:
GetCurrentRoom()→ MRUKRoomRegisterSceneLoadedCallback(UnityAction)— 如果场景已加载,则立即触发LoadSceneFromDevice(SceneModel)→ Task<LoadDeviceResult>LoadSceneFromPrefab(GameObject)→ Task<LoadDeviceResult>LoadSceneFromJsonString(string)→ Task<LoadDeviceResult>SaveSceneToJsonString()→ stringClearScene()HasSceneModel()→ Task<bool>(静态方法,用于检查设备是否有场景数据)ShareRoomsAsync(...)、LoadSceneFromSharedRooms(...)— 用于同地多人游戏
事件:SceneLoadedEvent、RoomCreatedEvent、RoomUpdatedEvent、RoomRemovedEvent
MRUKSettings(序列化配置):DataSource、RoomPrefabs[]、SceneJsons[]、LoadSceneOnStartup、EnableHighFidelityScene、SeatWidth、TrackerConfiguration
MRUKRoom
主要属性:Anchors、WallAnchors、FloorAnchors、CeilingAnchors、GlobalMeshAnchor、IsLocal、RoomMeshData
主要方法:
Raycast(Ray, float, out RaycastHit, out MRUKAnchor)— 对场景几何体执行无碰撞射线检测RaycastAll(...)— 检测所有交点IsPositionInRoom(Vector3)、IsPositionInSceneVolume(Vector3)TryGetClosestSurfacePosition(Vector3, out Vector3, out MRUKAnchor, LabelFilter)→ float(距离)GenerateRandomPositionOnSurface(SurfaceType, float, LabelFilter, out Vector3, out Vector3)→ boolGenerateRandomPositionInRoom(float, bool)→ Vector3?FindLargestSurface(SceneLabels)→ MRUKAnchorGetRoomBounds()→ BoundsGetKeyWall(out Vector2, float)→ MRUKAnchor(面向房间中心的最宽墙壁)
事件:AnchorCreatedEvent、AnchorUpdatedEvent、AnchorRemovedEvent
MRUKAnchor
主要属性:Label(SceneLabels)、PlaneRect(Rect?)、VolumeBounds(Bounds?)、PlaneBoundary2D(List<Vector2>)、Room(MRUKRoom)、ParentAnchor、ChildAnchors、GlobalMesh(Mesh)
主要方法:
Raycast(Ray, float, out RaycastHit, ComponentType)— 无碰撞射线检测HasAnyLabel(SceneLabels)→ boolGetAnchorCenter()→ Vector3GetClosestSurfacePosition(Vector3, out Vector3, out Vector3, ComponentType)→ floatIsPositionInVolume(Vector3)、IsPositionInBoundary(Vector2)
MRUKTrackable(继承自 MRUKAnchor)
运行时追踪的对象(键盘、QR 码)。由 MRUK 通过 SceneSettings.TrackerConfiguration 管理。
主要属性:TrackableType(OVRAnchor.TrackableType)、IsTracked、MarkerPayloadString、MarkerPayloadBytes
SceneSettings 上的事件:TrackableAdded、TrackableRemoved
功能组件
AnchorPrefabSpawner(Scripts/AnchorPrefabSpawner.cs)
根据标签在场景锚点上生成预制件。配置 PrefabsToSpawn(List<AnchorPrefabGroup>),将标签映射到预制件列表,并设置缩放/对齐模式。
AnchorPrefabGroup:Labels、Prefabs、PrefabSelection(Random/ClosestSize/Custom)、Scaling(Stretch/UniformScaling/UniformXZScale/NoScaling/Custom)、Alignment(Automatic/Bottom/Center/NoAlignment/Custom)、MatchAspectRatio、CalculateFacingDirection
方法:SpawnPrefabs()、SpawnPrefabs(MRUKRoom)、ClearPrefabs()
FindSpawnPositions(Scripts/FindSpawnPositions.cs)
生成用于放置对象的随机有效位置。支持悬浮、表面放置和悬挂位置,并进行物理重叠检查。
SpawnLocation 枚举:Floating、AnySurface、VerticalSurfaces、OnTopOfSurfaces、HangingDown
主要属性:SpawnObject、SpawnAmount、MaxIterations、Labels、CheckOverlaps、SurfaceClearanceDistance
GridSliceResizer(Scripts/GridSliceResizer.cs)
27 切片 3D 网格缩放器(9 切片的 3D 对应实现)。拉伸内部以匹配锚点尺寸,同时保留网格边缘/角落。将其附加到与 AnchorPrefabSpawner 配合使用的预制件上。
EffectMesh(Scripts/EffectMesh.cs)
根据场景锚点生成可视网格。支持材质、碰撞体、切割孔洞(用于门/窗)、投射阴影和切换可见性。
主要属性:MeshMaterial、Colliders、CutHoles(要切割孔洞的 SceneLabels)、CastShadow、HideMesh
方法:CreateMesh()、DestroyMesh()、ToggleEffectMeshVisibility(bool)、ToggleEffectMeshColliders(bool)
Passthrough Relighting (PTRL)
通过使用 Meta/MRUK/Scene/HighlightsAndShadows 着色器(TransparentSceneAnchor.mat)渲染 EffectMesh,将虚拟灯光的阴影和高光投射到真实世界表面。此功能很容易静默失效——最常见的问题是 URP Renderer 资源的 Transparent Receive Shadows 标志必须设为 ON,否则地面上不会出现阴影。
有关设置、URP/EffectMesh/透视要求、常见故障模式和编辑器验证,请参阅 references/passthrough-relighting.md。
DestructibleGlobalMeshSpawner (Scripts/DestructibleGlobalMeshSpawner.cs)
使用基于 Voronoi 的分割将全局网格划分为可破坏碎片。
主要属性:GlobalMeshMaterial、PointsPerUnitX/Y/Z(密度)、ReservedTop/Bottom(不可破坏区域)
SpaceMapGPU (Scripts/SpaceMapGPU.cs)
通过 GPU 计算房间布局的二维俯视距离场。输出到 RenderTexture。
主要属性:TextureDimension、MapGradient;方法:GetSpaceMap() → RenderTexture、GetColorAtPosition(Vector3) → Color
设置着色器全局变量 _SpaceMapProjectionViewMatrix,用于 UV 计算。
RoomGuardian (Scripts/RoomGuardian.cs)
当用户靠近房间墙壁时淡化边界材质。在材质上设置 _GuardianFade 浮点值。
主要属性:GuardianMaterial、GuardianDistance(米,默认值为 1.0)
SceneNavigation (Scripts/SceneNavigation.cs)
根据场景几何体生成 Unity NavMesh。需要 com.unity.ai.navigation。
主要属性:NavigableSurfaces(SceneLabels)、Agents(List<NavMeshAgent>)、AgentRadius
事件:OnNavMeshInitialized
更多信息请参阅 references/scene-navigation.md。
EnvironmentRaycastManager (Scripts/EnvironmentRaycastManager.cs)
针对物理环境进行深度 API 射线检测,无需预扫描场景数据。需要 Quest 3 或更高版本。命名空间:Meta.XR。
使用前检查 EnvironmentRaycastManager.IsSupported。
方法:Raycast(Ray, out EnvironmentRaycastHit, float)、PlaceBox(Ray, Vector3, Vector3, out EnvironmentRaycastHit)、CheckBox(Vector3, Vector3, Quaternion)
PassthroughCameraAccess (Scripts/PassthroughCameraAccess.cs)
访问原始透视摄像头图像。需要在 AndroidManifest 中添加 horizonos.permission.HEADSET_CAMERA。仅支持 Quest 3 或更高版本。命名空间:Meta.XR。
主要属性:CameraPosition(左/右)、RequestedResolution、MaxFramerate、TargetMaterial
方法:GetTexture() → Texture、GetColors() → NativeArray<Color32>(开销较大)、GetCameraPose() → Pose、ViewportPointToRay()、WorldToViewportPoint()
结构体 CameraIntrinsics:FocalLength、PrincipalPoint、SensorResolution、LensOffset
即时内容放置(Scripts/BuildingBlocks/InstantContentPlacement/)
使用 EnvironmentRaycastManager 实现无需设备扫描即可放置内容的构建块脚本:
SpaceLocator(抽象类):TryLocateSpace(out Pose)、OnSpaceLocateCompleted事件、PreferredSurfaceOrientationPointAndLocate:从 Transform 发射射线,提供Locate()方法GrabAndLocate:通过 Interaction SDK 抓取并释放以放置内容PlaceWithAnchor:在放置位置创建OVRSpatialAnchor,以防止漂移
常见模式
场景加载回调
void Start()
{
MRUK.Instance.RegisterSceneLoadedCallback(OnSceneLoaded);
}
void OnSceneLoaded()
{
var room = MRUK.Instance.GetCurrentRoom();
// Scene is ready — query anchors, spawn objects, etc.
}
如果场景已加载,RegisterSceneLoadedCallback 会立即触发,可随时安全调用。
使用 LabelFilter 遍历锚点
var room = MRUK.Instance.GetCurrentRoom();
foreach (var anchor in room.Anchors)
{
if (anchor.HasAnyLabel(MRUKAnchor.SceneLabels.TABLE | MRUKAnchor.SceneLabels.STORAGE))
{
Debug.Log($"{anchor.Label} at {anchor.GetAnchorCenter()}");
}
}
对房间几何体进行射线检测
var room = MRUK.Instance.GetCurrentRoom();
var ray = new Ray(origin, direction);
if (room.Raycast(ray, Mathf.Infinity, out var hit, out var anchor))
{
Debug.Log($"Hit {anchor.Label} at {hit.point}, normal {hit.normal}");
}
使用预制件回退进行编辑器测试
将 MRUK.SceneSettings.DataSource 设为 DeviceWithPrefabFallback,并在 SceneSettings.RoomPrefabs 中指定房间预制件。在设备上使用真实场景数据。在编辑器中(未连接设备时),会自动加载预制房间。此包在 Core/Rooms/Prefabs/ 下包含约 50 个示例房间预制件(卧室、客厅、办公室、大型空间)。
项目设置
- 安装
com.meta.xr.mrutilitykit包 - 在 OVRManager > Quest Features 中,将 Scene Support 设为 "Required"
- 在 OVRManager > Quest Features 中,启用 Anchor Support
- 确保场景中有
OVRCameraRig - 在场景中添加一个带有
MRUK组件的MRUKGameObject - 配置
SceneSettings.DataSource(开发时使用DeviceWithPrefabFallback) - 对于 PassthroughCameraAccess:将
horizonos.permission.HEADSET_CAMERA添加到 AndroidManifest,并通过OVRManifestPreprocessor.GenerateOrUpdateAndroidManifest(true)重新生成 — 必须设置silentMode: true,否则生成器会打开一个阻止请求的模态对话框。完整的清单工作流请参阅hz-unity-meta-core-sdk。
运行 MRUK 代码 — 使用 unity-cli 驱动运行中的 Editor
MRUK 设置仅支持 Editor C#。请在已打开的 Editor 中运行,而不要手动编辑场景或设置文件:
unity status --format json # look for state "ready"
unity command run_script --file AgentScripts/SetupMRUK.cs --entry SetupMRUK.Run --format json
将 .cs 文件放在 Assets/ 之外(相对于项目根目录的路径),这样写入文件就不会触发导入或域重载;并添加 --dry_run true,在修改任何内容前进行编译检查。
run_script 会引用所有已加载的程序集,因此可以直接引用 Meta.XR.MRUtilityKit 命名空间,无需反射:
// AgentScripts/SetupMRUK.cs
using Meta.XR.MRUtilityKit;
public static class SetupMRUK
{
public static string Run()
{
var room = MRUK.Instance.GetCurrentRoom();
return room == null ? "no current room" : $"room: {room.name}";
}
}
- 这里
using System.Reflection;和BindingFlags重载都可用,因此只有在访问确实为非公开的成员时才需要反射。 - 所有异步操作都会在脚本返回后完成 — 请在单独的后续
run_script中验证,切勿在主线程上调用Task.Wait()。 - 场景更改完成后,使用
EditorSceneManager.MarkSceneDirty+SaveScene或unity command save_scene,然后读回该值。
MRUK 是一个运行时系统,因此大部分内容只有在 Play 模式下才会生成数据。请通过 CLI 驱动运行:
unity command clear_console --format json
unity command editor_play --format json # blocks until play mode is live
unity command get_console_logs --severity error --format json
unity command editor_stop --format json
停止前请给场景留出足够时间。 editor_play 会在 Play 模式启动后返回,而不是等 MRUK 完成 — LoadSceneFromDevice / LoadSceneFromPrefab 会返回一个 Task,而 EffectMesh、SceneNavigation 等组件只会在 SceneLoadedEvent 触发后运行。立即停止会导致这些操作无法完成。请轮询 get_console_logs(或使用读取 MRUK.Instance.IsInitialized 的 run_script),直到场景加载完成,然后再读取错误并停止。
连接、--project-path 和安全模式恢复说明请参阅 unity-cli 技能。基于反射的 MCP 版本请参阅 references/unity-mcp-fallback.md。
使用 metavr 工具获取最新文档
如果 metavr MCP 服务可用,请使用 mcp__metavr__vr_docs_search 和 mcp__metavr__vr_docs_get_page 工具核实当前 API 详情,因为 Meta SDK 文档会频繁更新。使用 mcp__metavr__vr_api_search 并设置 engine='unity',查询 MRUK、MRUKRoom、MRUKAnchor 和其他类的确切方法签名。也可通过 CLI 访问同一后端:metavr docs search "<topic>" 和 metavr docs api-search "<Class.method>"。
文档链接
- MR Utility Kit 概览
- MRUK API 参考
- GitHub 示例(12 个示例场景,自 v76 起已从包中移出)
- Scene API 概览