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

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

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

备注

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

命名空间和文件夹结构

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

  1. 第三方加载项
  2. Microsoft Mixed Reality Toolkit

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

第三方加载项

命名空间

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

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

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

文件夹结构

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

文件夹结构示例

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

MRTK 提交

命名空间

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

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

文件夹结构

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

定义空间数据对象

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

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

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

实现数据提供程序

指定接口和/或基类继承

所有空间感知数据提供程序都必须实现 接口,该接口指定空间感知系统所需的 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 Profiler 检测

性能在混合现实应用程序中至关重要。 每个组件都会增加应用程序必须考虑到的一些开销。 为此,所有空间感知数据提供程序在内部循环和经常使用的代码路径中包含 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;
}

属性可应用于配置文件类,使客户能够使用"创建资产""混合现实"Toolkit CreateAssetMenu > > > 配置文件"菜单创建配置文件 实例。

实现检查器

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

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

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

创建程序集 ()

混合现实Toolkit使用程序集定义 (.asmdef) 文件来指定组件之间的依赖关系,以及帮助 Unity 减少编译时间。

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

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

第一个程序集定义用于数据访问接口。 对于此示例,它将称为 ContosoSpatialAwareness,将位于示例的 ContosoSpatialAwareness 文件夹中。 此程序集定义必须指定对 Microsoft.MixedReality 的依赖关系。Toolkit及其依赖的其他任何程序集。

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

  • Microsoft.MixedReality。Toolkit
  • Microsoft.MixedReality。Toolkit。Editor.Inspectors
  • Microsoft.MixedReality。Toolkit。Editor.Utilities

注册数据提供程序

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

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

打包和分发

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

如果提交数据提供程序并将其作为 Microsoft Mixed Reality Toolkit 包的一部分接受,Microsoft MRTK 团队将打包并分发它作为 MRTK 产品/服务一部分。

另请参阅