mcpField
H
hz-unity-meta-mixed-reality-utility-kit

hz-unity-meta-mixed-reality-utility-kit

github.com/meta-quest开发241197 次安装5 周前更新
代码仓库

关于 hz-unity-meta-mixed-reality-utility-kit

hz-unity-meta-mixed-reality-utility-kit 是面向使用 Meta MR Utility Kit 构建场景感知混合现实体验的 Unity 技能参考。内容涵盖场景数据、空间查询、表面放置、房间几何与可追踪对象,并列出 API 入口和包配置细节。

主要功能

  1. 01从设备或文件加载场景数据
  2. 02查询房间几何与表面
  3. 03在场景锚点上生成预制件
  4. 04根据房间几何生成 NavMesh
  5. 05访问透视摄像头与可追踪对象

适用场景

  1. 01在检测到的真实表面放置内容
  2. 02为 MR 交互查询房间几何
  3. 03根据扫描房间构建导航
  4. 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.md
scene-navigation.md
unity-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

然后在后续所有搜索操作中使用解析出的父路径。

快速参考

任务类 / 组件源文件关键入口点
从设备加载场景MRUKScripts/MRUK.csLoadSceneFromDevice()
从预制件 / JSON 加载场景MRUKScripts/MRUK.csLoadSceneFromPrefab()、LoadSceneFromJsonString()
获取当前房间MRUKScripts/MRUK.csGetCurrentRoom()
防止锚点漂移MRUKScripts/MRUK.csEnableWorldLock = true
查询房间几何体MRUKRoomScripts/MRUKRoom.csRaycast()、IsPositionInRoom()
查找表面 / 最近点MRUKRoomScripts/MRUKRoom.csTryGetClosestSurfacePosition()、GenerateRandomPositionOnSurface()
获取锚点属性MRUKAnchorScripts/MRUKAnchor.csLabel、PlaneRect、VolumeBounds
在锚点上生成预制件AnchorPrefabSpawnerScripts/AnchorPrefabSpawner.csPrefabsToSpawn、SpawnOnStart
查找随机生成位置FindSpawnPositionsScripts/FindSpawnPositions.csStartSpawn()、SpawnLocations
27 切片网格缩放GridSliceResizerScripts/GridSliceResizer.csResizeTo(Vector3)
生成视觉网格EffectMeshScripts/EffectMesh.csCreateMesh()、CutHoles
可破坏的场景几何体DestructibleGlobalMeshSpawnerScripts/DestructibleGlobalMeshSpawner.csCreateOnRoomLoaded
GPU 距离场纹理SpaceMapGPUScripts/SpaceMapGPU.csGetSpaceMap()、StartSpaceMap()
靠近边界时渐隐RoomGuardianScripts/RoomGuardian.csGuardianDistance、GuardianMaterial
根据场景生成 NavMeshSceneNavigationScripts/SceneNavigation.csBuildSceneNavMesh()
深度 API 射线检测EnvironmentRaycastManagerScripts/EnvironmentRaycastManager.csRaycast()、PlaceBox()
透视摄像头图像PassthroughCameraAccessScripts/PassthroughCameraAccess.csGetTexture()、GetCameraPose()
跟踪键盘 / QR 码MRUKTrackableScripts/MRUKTrackable.csTrackableType、MarkerPayloadString
即时放置(无需扫描)PointAndLocateScripts/BuildingBlocks/InstantContentPlacement/TryLocateSpace()
共享房间(多人游戏)MRUKScripts/MRUK.csShareRoomsAsync()、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)都遵循相同的模式:

  1. SpawnOnStart / CreateOnStart / BuildOnSceneLoaded 属性的类型为 MRUK.RoomFilter,用于控制自动初始化
  2. 在 Start() 中,它们会调用 MRUK.Instance.RegisterSceneLoadedCallback(...);如果场景已加载,该回调会立即触发
  3. 它们还提供手动方法(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() → MRUKRoom
  • RegisterSceneLoadedCallback(UnityAction) — 如果场景已加载,则立即触发
  • LoadSceneFromDevice(SceneModel) → Task<LoadDeviceResult>
  • LoadSceneFromPrefab(GameObject) → Task<LoadDeviceResult>
  • LoadSceneFromJsonString(string) → Task<LoadDeviceResult>
  • SaveSceneToJsonString() → string
  • ClearScene()
  • 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) → bool
  • GenerateRandomPositionInRoom(float, bool) → Vector3?
  • FindLargestSurface(SceneLabels) → MRUKAnchor
  • GetRoomBounds() → Bounds
  • GetKeyWall(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) → bool
  • GetAnchorCenter() → Vector3
  • GetClosestSurfacePosition(Vector3, out Vector3, out Vector3, ComponentType) → float
  • IsPositionInVolume(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 事件、PreferredSurfaceOrientation
  • PointAndLocate:从 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 个示例房间预制件(卧室、客厅、办公室、大型空间)。

项目设置

  1. 安装 com.meta.xr.mrutilitykit 包
  2. 在 OVRManager > Quest Features 中,将 Scene Support 设为 "Required"
  3. 在 OVRManager > Quest Features 中,启用 Anchor Support
  4. 确保场景中有 OVRCameraRig
  5. 在场景中添加一个带有 MRUK 组件的 MRUK GameObject
  6. 配置 SceneSettings.DataSource(开发时使用 DeviceWithPrefabFallback)
  7. 对于 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>"。

文档链接

评论

支持 Markdown