Version: 2018.2
以下是__空间映射渲染器 (Spatial Mapping Renderer)__ 和__空间映射碰撞体 (Spatial Mapping Collider)__ 组件的共同设置。
空间映射渲染器 (Spatial Mapping Renderer)

空间映射碰撞体 (Spatial Mapping Collider)

__空间映射碰撞体__组件允许全息内容与真实世界的物理表面进行交互。该组件负责在场景中创建、更新和销毁表面游戏对象碰撞体。

该组件定期向系统查询物理世界中的表面更改。当系统报告有表面更改时,__空间映射碰撞体__组件会确定 Unity 对每个报告的表面进行烘焙的先后时间。系统每次烘焙表面时,Unity 都会生成一个新的游戏对象,使其包含网格过滤器 (Mesh Filter)网格碰撞体 (Mesh Collider) 组件。与 Unity 中的任何其他网格一样,具有网格碰撞体的表面允许与射线投射进行碰撞。请参阅摄像机射线投射文档以了解更多信息。

__注意:__此组件仅更新表面游戏对象的网格碰撞体组件,而不更新网格渲染器 (Mesh Renderer)。

注意:空间映射碰撞体__的更新延迟比__空间映射网格渲染器 (Spatial Mapping Mesh Renderer) 更短。这意味着碰撞体的更新速度比渲染器快。

Unity Editor 中显示的空间映射碰撞体 (Spatial Mapping Collider) 组件
Unity Editor 中显示的空间映射碰撞体 (Spatial Mapping Collider) 组件

Collider Settings

设置 描述
Enable Collisions 选中此框可启用表面网格碰撞体。这意味着全息内容可与表面发生碰撞。
Mesh Layer 设置所有表面网格碰撞体上的层 (Layer) 属性。请注意,需要为射线投射设置层 (Layers)。执行射线投射时,必须指明要根据哪些层来测试射线交点。请参阅摄像机射线投射文档以了解更多信息,并参阅下面的示例脚本:SpatialSurface 射线投射

默认情况下,Unity 将所有游戏对象分配到__默认 (Default)__ 层。但是,最好将游戏对象分配给特定的层。我们建议专门为空间映射表面创建一个新层,并将此层分配给 Mesh Layer 属性。
Physic Material 指定要分配给每个表面游戏对象的网格碰撞体的__物理材质 (Physic Material)。默认设置为 None (Physic Material)

物理材质__指定其他刚体组件应如何与其交互。例如,您可能希望创建一个表面来模拟冰面,因此对该表面上移动的游戏对象施加较小的摩擦力。

空间映射碰撞体组件将其__物理材质__应用于其表面游戏对象上的所有网格碰撞体。请参阅有关物理材质的文档以了解更多信息

General Settings

以下是__空间映射渲染器 (Spatial Mapping Renderer)__ 和__空间映射碰撞体 (Spatial Mapping Collider)__ 组件的共同设置。

设置 描述
Surface Parent 选择希望由空间映射组件生成的表面游戏对象继承自的__表面父级 (Surface Parent)__ 游戏对象。将此设置保留为 None(Game Object) 可自动生成表面父游戏对象。
Freeze Updates 选中此复选框可停止组件向系统查询表面更改。

注意:__每个空间映射组件会定期在空间映射数据中查询物理空间中的表面更改。查询和烘焙表面的过程存在内存、性能和功耗方面的成本。对于希望基本为静态的环境,建议让用户在一段时间内观察环境而不更新表面游戏对象。

如果希望模拟中的环境在很大程度上为静态且不变(如棋盘游戏),可以在应用程序启动时预先扫描所需的表面数据,然后将
Freeze Updates__ 属性设置为 true 以防止进一步更新。这样可以略微提高性能并降低功耗。
Time Between Updates 指定对物理空间中的表面更改进行查询的间隔时间(以小数格式的秒为单位,如 3.7 或 4.6)。默认值为 2.5 秒。请注意,查询越频繁,内存、性能和功耗的成本就越高。
Removal Update Count 在系统删除表面游戏对象之前的更新次数。在此上下文中,可将一次更新视为一帧。默认为 10 次更新。

注意:__当空间映射通知组件表面游戏对象不再位于 SurfaceObserver 的包围体中时(即不再位于系统报告的规定区域中时),将开始进行删除更新倒计时。此设置允许您指定此事件之后在空间映射删除表面游戏对象之前应执行的更新次数。 | | Level of Detail| 组件生成的网格质量(__LowMediumHigh__)。默认质量为 Medium。质量越高,生成的碰撞体或渲染网格越精细和准确。使用较低质量的设置可以在性能和功耗方面降低成本。请参阅此表下的图了解三个 Level Of Detail__ 模式的示例。
Bounding Volume Type 组件的包围体区域形状,应用程序在其中接收空间映射数据。此设置可以是 SphereAxis Aligned Box。默认为 Axis Aligned Box

注意:__包围体是系统报告物理表面更改并限制空间映射网格范围的规定区域。| | Size In Meters| 组件使用的包围体的大小(以米为单位)。按半径配置 Sphere__;默认半径为 2 米。按面积配置 Axis Aligned Box__;默认值为 Vector3 (4,4,4)。

注意:__观察者的包围体是供空间映射报告物理表面更改的规定区域。

Level of Detail

两个空间映射组件都允许为每个组件生成的空间网格指定三个细节级别之一(Low、Medium 或 High),如下图所示。

空间映射网格的三个细节级别模式
空间映射网格的三个细节级别模式

如果可能,请将 Spatial Mapping Colliders 的 Level of Detail 设置为 Low。这样将在计算碰撞交点时提高性能并降低功耗。但是,将 Level of Detail 设置为 Low 可能会对应用程序的视觉效果产生负面影响。

使用空间映射碰撞体

表面游戏对象

将__空间映射碰撞体__组件添加到场景中的游戏对象时,该组件会在运行时生成自己独立的一组表面游戏对象。这些游戏对象出现在场景中作为一个表面父游戏对象的子项。

__空间映射碰撞体__生成的表面游戏对象包含以下组件:

__空间映射碰撞体__生成的表面游戏对象的组件
__空间映射碰撞体__生成的表面游戏对象的组件

如果将多个__空间映射碰撞体__组件添加到场景,则每个组件都会生成自己的一组表面游戏对象。例如,如果场景中的两个游戏对象包含__空间映射碰撞体__,则场景将包含两组表面游戏对象:每个组件在运行时生成一组。为了优化目的,请务必牢记这一点。

注意:__所有__表面游戏对象__首次由空间映射系统生成时都会分配给__默认层 (Default Layer)。但是,最好将游戏对象分配给特定层,因为射线投射是一项高成本的计算。通过使用层,可以过滤要进行射线投射计算的游戏对象,从而可以优化性能。如果__默认__层上没有很多复杂的网格,那么对碰撞进行射线投射测试不会产生很大的性能成本。但是,为了在进行碰撞时降低射线投射测试的复杂性,最好将游戏对象按层进行组织。通过更改 Collider Settings > Mesh Layer 属性,即可更改分配给特定__空间映射碰撞体__组件生成的所有表面游戏对象的层。

示例脚本:发生点击手势事件时的 SpatialSurface 射线投射

以下示例展示了在检测到点击手势事件时,如何在 SpatialSurface 层上对游戏对象进行射线投射,并使用 GestureRecognizer 启动此射线投射。


using UnityEngine;
using System.Collections; 

//这是 Gesture Recognizer 所必需的
using UnityEngine.XR.WSA.Input;


public class CustomLayerCollision : MonoBehaviour
{

    //用于捕捉手势事件

    private GestureRecognizer GR_recognizer;

    void Start()
    {
        //初始化 GestureRecognizer

        GR_recognizer = new GestureRecognizer();

        //启动手势捕捉

        GR_recognizer.StartCapturingGestures();

        //告知 GestureRecognizer 需要监听的事件

        GR_recognizer.SetRecognizableGestures(GestureSettings.Tap);

        //将 Tapped 事件订阅到 DetectCollisions 方法

        //这样可确保在 GestureRecognizer 检测到点击事件时立即调用此方法

        GR_recognizer.Tapped += DetectCollisions;

        //当用户发出点击手势时,Tapped 事件委托

        //会调用 DetectCollisions 方法来使用射线投射进行碰撞测试

        //请参阅 [GestureRecognizer API 参考](../ScriptReference/XR.WSA.Input.GestureRecognizer.html)了解更多详细信息
    }
    //发生点击事件时用于触发射线投射的方法
    public void DetectCollisions(TappedEventArgs tapEvent)
    {
        // 对空间表面或 UI 层上的所有游戏对象
        // 进行射线投射。

        int layerMask = 1 << LayerMask.NameToLayer("SpatialSurface");

        //使用用户头部的位置和前进方向构造 Ray
        Ray GazeRay = new Ray(tapEvent.headPose.position, tapEvent.headPose.forward);

        //使用 Gaze 中构造的 Ray 进行射线投射并将碰撞存储在阵列命中内

        RaycastHit[] hits = Physics.RaycastAll(GazeRay, float.MaxValue, layerMask);

        if (hits.Length > 0)
        {
            foreach (RaycastHit hit in hits)
            {
                Debug.Log(string.Format("Hit Object **\"**{0}**\"** at position **\"**{1}**\"**", hit.collider.gameObject, hit.point));
            }
        }
        else
        {
            Debug.Log("Nothing was hit.");
        }
    }
}

请参阅有关摄像机射线投射的文档以了解更多信息。

  • 2018–05–01 页面已发布并进行了编辑审查

  • 在 2017.3 版中更新了 Hololens 空间映射文档

以下是__空间映射渲染器 (Spatial Mapping Renderer)__ 和__空间映射碰撞体 (Spatial Mapping Collider)__ 组件的共同设置。
空间映射渲染器 (Spatial Mapping Renderer)