创建空间感知系统数据提供程序 — MRTK2

空间感知系统是一个可扩展的系统,用于为应用程序提供有关真实环境的数据。 若要添加对新硬件平台或新形式的空间感知数据的支持,可能需要自定义数据提供程序。

本文介绍如何为空间感知系统 创建自定义数据提供程序,也称为空间观察程序。 此处显示的示例代码来自类实现, SpatialObjectMeshObserver 这对于 在编辑器中加载 3D 网格数据很有用

注意

可以在 文件夹中找到 Assets/MRTK/Providers/ObjectMeshObserver 此示例中使用的完整源代码。

命名空间和文件夹结构

可以通过以下两种方式之一来分发数据提供程序:

  1. 第三方加载项
  2. Microsoft 混合现实 工具包的一部分

向 MRTK 提交新数据提供程序的审批流程将因具体情况而异,并将在初始建议书时传达。 可以通过创建新的 功能请求 类型问题来提交建议。

第三方加载项

命名空间

数据提供程序需要有一个命名空间来缓解潜在的名称冲突。 建议命名空间包含以下组件。

  • 生产加载项的公司名称
  • 功能区域

例如,Contoso 公司创建和交付的空间感知数据提供程序可能是“Contoso.MixedReality.Toolkit.SpatialAwareness”。

文件夹结构

建议将数据提供程序的源代码布局在文件夹层次结构中,如下图所示。

示例文件夹结构

其中 ContosoSpatialAwareness 文件夹包含数据提供程序的实现,编辑器 文件夹包含检查器 (和任何其他Unity编辑器特定代码) ,并且 Profiles 文件夹包含一个或多个预制的配置文件可编写脚本的对象。

MRTK 提交

命名空间

如果将空间感知系统数据提供程序提交到 混合现实 Toolkit 存储库,命名空间必须以 Microsoft.MixedReality.Toolkit (例如:Microsoft.MixedReality.Toolkit.SpatialObjectMeshObserver)

代码应位于 MRTK/Providers (例如 MRTK/Providers/ObjectMeshObserver) 下的文件夹中。

文件夹结构

所有代码都应位于 MRTK/Providers 的文件夹中, (例如 MRTK/Providers/ObjectMeshObserver) 。

定义空间数据对象

创建空间感知数据提供程序的第一步是确定 (数据类型,例如:网格或平面,) 它将提供给应用程序。

所有空间数据对象都必须实现 IMixedRealitySpatialAwarenessObject 接口。

混合现实工具包基础提供以下空间对象,可以在新的数据提供程序中使用或扩展这些对象。

实现数据提供程序

指定接口和/或基类继承

所有空间感知数据提供程序都必须实现 IMixedRealitySpatialAwarenessObserver 接口,该接口指定空间感知系统所需的最低功能。 MRTK 基础包括 类, BaseSpatialObserver 该类提供此所需功能的默认实现。

public class SpatialObjectMeshObserver :
    BaseSpatialObserver,
    IMixedRealitySpatialAwarenessMeshObserver,
    IMixedRealityCapabilityCheck
{ }

注意

IMixedRealityCapabilityCheck类使用 SpatialObjectMeshObserver 接口来指示它提供对 SpatialAwarenessMesh 功能的支持。

应用 MixedRealityDataProvider 属性

创建空间感知数据提供程序的关键步骤是将 MixedRealityDataProvider 属性应用于 类。 此步骤允许在空间感知配置文件以及名称、文件夹路径等中选择数据提供程序的默认配置文件和平台 () 。

[MixedRealityDataProvider(
    typeof(IMixedRealitySpatialAwarenessSystem),
    SupportedPlatforms.WindowsEditor | SupportedPlatforms.MacEditor | SupportedPlatforms.LinuxEditor,
    "Spatial Object Mesh Observer",
    "ObjectMeshObserver/Profiles/DefaultObjectMeshObserverProfile.asset",
    "MixedRealityToolkit.Providers")]
public class SpatialObjectMeshObserver :
    BaseSpatialObserver,
    IMixedRealitySpatialAwarenessMeshObserver,
    IMixedRealityCapabilityCheck
{ }

实现 IMixedRealityDataProvider 方法

定义 类后,下一步是提供 接口的 IMixedRealityDataProvider 实现。

注意

BaseSpatialObserver 通过 BaseService 类仅为 IMixedRealityDataProvider 方法提供空实现。 这些方法的详细信息通常是特定于数据提供程序的。

数据提供程序应实现的方法包括:

  • Destroy()
  • Disable()
  • Enable()
  • Initialize()
  • Reset()
  • Update()

实现数据提供程序逻辑

下一步是通过实现特定的数据提供程序接口(例如 IMixedRealitySpatialAwarenessMeshObserver),添加数据访问接口的逻辑。 数据提供程序的这一部分通常是特定于平台的。

观察更改通知

为了允许应用程序响应设备对环境理解的更改,数据提供程序会引发接口中 IMixedRealitySpatialAwarenessObservationtHandler<T> 定义的通知事件。

  • OnObservationAdded()
  • OnObservationRemoved()
  • OnObservationUpdated()

示例中的 SpatialObjectMeshObserver 以下代码演示了添加网格数据时引发 和 事件。

// The data to be sent when mesh observation events occur.
// This member variable is initialized as part of the Initialize() method.
private MixedRealitySpatialAwarenessEventData<SpatialAwarenessMeshObject> meshEventData = null;

/// <summary>
/// Sends the observations using the mesh data contained within the configured 3D model.
/// </summary>
private void SendMeshObjects()
{
    if (!sendObservations) { return; }

    if (spatialMeshObject != null)
    {
        MeshFilter[] meshFilters = spatialMeshObject.GetComponentsInChildren<MeshFilter>();
        for (int i = 0; i < meshFilters.Length; i++)
        {
            SpatialAwarenessMeshObject meshObject = SpatialAwarenessMeshObject.Create(
                meshFilters[i].sharedMesh,
                MeshPhysicsLayer,
                $"Spatial Object Mesh {currentMeshId}",
                currentMeshId,
                ObservedObjectParent);

            meshObject.GameObject.transform.localPosition = meshFilters[i].transform.position;
            meshObject.GameObject.transform.localRotation = meshFilters[i].transform.rotation;

            ApplyMeshMaterial(meshObject);

            meshes.Add(currentMeshId, meshObject);

            // Initialize the meshEventData variable with data for the added event.
            meshEventData.Initialize(this, currentMeshId, meshObject);
            // Raise the event via the spatial awareness system.
            SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);

            currentMeshId++;
        }
    }

    sendObservations = false;
}

注意

SpatialObjectMeshObserver 不会引发 OnObservationUpdated 事件,因为 3D 模型仅加载一次。 类中的 WindowsMixedRealitySpatialMeshObserver 实现提供了为观察到的网格引发 OnObservationUpdated 事件的示例。

添加Unity探查器检测

性能在混合现实应用程序中至关重要。 每个组件都会增加一些应用程序必须考虑到的开销。 为此,所有空间感知数据提供程序在内部循环和经常使用的代码路径中包含Unity Profiler 检测,这一点非常重要。

建议在检测自定义提供程序时实现 MRTK 使用的模式。

        private static readonly ProfilerMarker UpdateObserverPerfMarker = new ProfilerMarker("[MRTK] WindowsMixedRealitySpatialMeshObserver.UpdateObserver");

        /// <summary>
        /// Requests updates from the surface observer.
        /// </summary>
        private void UpdateObserver()
        {
            using (UpdateObserverPerfMarker.Auto())
            {
                // Code to be measured.
            }
        }

注意

用于标识探查器标记的名称是任意的。 MRTK 使用以下模式。

“[product] className.methodName - 可选注释”

建议自定义数据提供程序遵循类似的模式,以帮助在分析跟踪时简化特定组件和方法的标识。

创建配置文件和检查器

在 混合现实 Toolkit 中,使用配置文件配置数据提供程序。

定义配置文件

配置文件内容应镜像数据提供程序的可访问属性 (例如:更新间隔) 。 每个接口中定义的所有用户可配置属性都应包含在配置文件中。

如果新的数据访问接口扩展了现有提供程序,则建议使用基类。 例如, SpatialObjectMeshObserverProfile 扩展 MixedRealitySpatialAwarenessMeshObserverProfile 了 ,使客户能够提供用作环境数据的 3D 模型。

[CreateAssetMenu(
    menuName = "Mixed Reality Toolkit/Profiles/Spatial Object Mesh Observer Profile",
    fileName = "SpatialObjectMeshObserverProfile",
    order = 100)]
public class SpatialObjectMeshObserverProfile : MixedRealitySpatialAwarenessMeshObserverProfile
{
    [SerializeField]
    [Tooltip("The model containing the desired mesh data.")]
    private GameObject spatialMeshObject = null;

    /// <summary>
    /// The model containing the desired mesh data.
    /// </summary>
    public GameObject SpatialMeshObject => spatialMeshObject;
}

属性CreateAssetMenu可以应用于配置文件类,使客户能够使用“创建>资产>混合现实工具包>配置文件”菜单创建配置文件实例

实现检查器

配置文件检查器是用于配置和查看配置文件内容的用户界面。 每个配置文件检查器应扩展 BaseMixedRealityToolkitConfigurationProfileInspector 类。

属性CustomEditor通知Unity检查器所应用的资产类型。

[CustomEditor(typeof(SpatialObjectMeshObserverProfile))]
public class SpatialObjectMeshObserverProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{ }

创建程序集定义 ()

混合现实工具包使用程序集定义 (.asmdef) 文件来指定组件之间的依赖关系,并帮助Unity缩短编译时间。

建议为所有数据提供程序及其编辑器组件创建程序集定义文件。

使用前面示例中 的文件夹结构 ,ContosoSpatialAwareness 数据提供程序将有两个 .asmdef 文件。

第一个程序集定义用于数据提供程序。 对于此示例,它将称为 ContosoSpatialAwareness,并将位于示例的 ContosoSpatialAwareness 文件夹中。 此程序集定义必须指定Microsoft.MixedReality.Toolkit 及其所依赖的任何其他程序集的依赖项。

ContosoInputEditor 程序集定义将指定配置文件检查器和任何编辑器特定的代码。 此文件必须位于编辑器代码的根文件夹中。 在此示例中,该文件将位于 ContosoSpatialAwareness\编辑器 文件夹中。 此程序集定义将包含对 ContosoSpatialAwareness 程序集的引用以及:

  • Microsoft.MixedReality.Toolkit
  • Microsoft.MixedReality.Toolkit。编辑器。督察
  • Microsoft.MixedReality.Toolkit。编辑器。公用事业

注册数据提供程序

创建后,可以将数据提供程序注册到空间感知系统,以在应用程序中使用。

选择空间对象网格观察程序

打包和分发

作为第三方组件分发的数据提供程序具有打包和分发的具体详细信息,留给开发人员的首选项。 最常见的解决方案可能是生成 .unitypackage 并通过 Unity 资产存储进行分发。

如果数据提供程序作为Microsoft 混合现实 工具包包的一部分提交并接受,Microsoft MRTK 团队将打包并分发为 MRTK 产品/服务的一部分。

另请参阅