Unity Hololens2开发|(十一)MRTK3 Solver(求解器)

2024-01-18 19:11:47 浏览数 (1)

1.前言

求解器是有助于根据预定义算法计算对象位置和方向的组件。 示例:将对象放置在与用户注视视线相交的表面。 求解器系统确定性地定义这些转换计算的运算顺序,因为没有可靠的方法向 Unity 指定组件的更新顺序。 求解器提供一系列行为,以将对象附加到其他对象或系统。 另一个示例是一个尾随对象,该对象悬停在用户前面(基于摄像机)。 求解器还可以附加到控制器和对象,使对象尾随控制器。 所有求解器都可以安全地堆叠,例如尾随行为加表面磁性加动量。

2.求解器的使用

  • 求解器系统由三类脚本组成:
    • Solver:抽象基类,所有求解器都派生自该类。 它提供状态跟踪、平滑参数和实现、自动求解器系统集成和更新顺序。
    • SolverHandler:设置跟踪的参照对象(例如:主摄像头转换、手部射线等),处理求解器组件收集以及按正确顺序执行更新。
    • 第三个类别是求解器本身。 以下求解器提供基本行为的构建基块:

求解器类型

描述

Orbital

锁定到指定位置并偏离参照对象

ConstantViewSize

应缩放以保持相对于参照对象视图不变的大小

RadialVie

使对象保持在参照对象的视锥投射范围内。

ConstantViewSize

应缩放以保持相对于参照对象视图不变的大小

Follow

使对象保持在参照对象的一组用户定义边界内。

InBetween

使对象保持在两个跟踪对象之间。

SurfaceMagnetism

将射线投射到世界中的表面上,并使对象对齐到该表面。

DirectionalIndicator

确定作为方向指示器的对象的位置和方向。 从 SolverHandler 跟踪目标的参照点来看,此指示器将面向提供的 DirectionalTarget。

Momentum

应用加速/速度/摩擦来模拟由其他求解器/组件移动的对象的动量和弹性。

HandConstraint

约束对象,使其在 GameObject 不会与手部交叉的区域跟随手部。 对手部约束的交互式内容(如菜单等)很有用。此求解器旨在与 XRNode 一起使用。

HandConstraintPalmUp:

派生自 HandConstraint,但包含用于测试手部在激活前是否手掌面向用户的逻辑。 此求解器只能与 XRNode 控制器一起使用,如果与其他控制器类型一起使用,此求解器的行为类似于基类。

Overlap

与跟踪的对象重叠。

3.更改跟踪参照

  • SolverHandler 组件的“TrackedTargetType”属性定义所有求解器将用于计算其算法的参考点。 例如,具有简单 SurfaceMagnetism 组件的 Head 值类型将产生从头部开始,沿着用户凝视方向发射出去的射线,用于求解射线到达的表面。 TrackedTargetType 属性的可能值包括:
    • Head:参照点是主摄像头的转换
    • ControllerRay:参考点是控制器上指向射线方向的 LinePointer 转换(即运动控制器或手操控制器上的指针原点), 使用 TrackedHandedness 属性选择惯用手偏好(即左手和/或右手)
    • HandJoint:参照点是特定手部关节的转换,使用 TrackedHandedness 属性选择惯用手偏好(即左手和/或右手),使用 TrackedHandJoint 属性确定要利用的联接转换。
    • CustomOverride:参照点来自于已分配的 TransformOverride

4.创建新的求解器

  • 所有求解器都必须继承自抽象基类 Solver。 求解器扩展的主要要求涉及重写 SolverUpdate 方法。 在此方法中,开发人员应将继承的 GoalPositionGoalRotationGoalScale 属性更新为所需值。 此外,将 SolverHandler.TransformTarget 用作使用者所需的参考系十分有益。
  • 下面提供的代码提供了名为 InFront 的新求解器组件的示例,该组件将附加对象放在 SolverHandler.TransformTarget 前面 2 米处。 如果使用者将 SolverHandler.TrackedTargetType 设置为 Head,则 SolverHandler.TransformTarget 将是相机转换,因此该求解器会在每一帧将附加的 GameObject 放在用户凝视的前面的 2 米处。
代码语言:javascript复制
public class InFront : Solver
{
    public override void SolverUpdate()
    {
        if (SolverHandler != null && SolverHandler.TransformTarget != null)
        {
            var target = SolverHandler.TransformTarget;
            GoalPosition = target.position   target.forward * 2.0f;
        }
    }
}

5.求解器属性

每个求解器组件都有一组核心属性,这些属性是相同的,用于控制求解器行为。 如果启用了“Smoothing”,则求解器将随着时间的推移,将 GameObject 的转换逐渐更新为计算值。 每个转换组件的“LerpTime”属性确定了此更改的速度。 例如,MoveLerpTime 值越高,帧之间的移动增量就会越慢。 如果启用了 MaintainScale,求解器将利用 GameObject 的默认局部缩放。

5.1.Orbital

  • Orbital 类是一个尾随组件,其行为类似于太阳系中的行星。 此求解器将确保附加的 GameObject 围绕着跟踪转换旋转。 因此,如果 SolverHandler 的“Tracked Target Type”设置为 Head,则 GameObject 将按照所应用的固定偏移量,围绕用户的头部旋转。
  • 可以修改此固定偏移量,以使菜单或其他场景组件保持在眼睛或腰部的高度,围绕在用户周围。 这可以通过更改“Local Offset(局部偏移量)”和“World Offset(全局偏移量)”属性完成。 “Orientation Type(方向类型)”属性确定应用于对象的旋转,例如,对象应始终保持原始旋转,或者总是面向摄像头,或者面向驱动其位置的转换。

5.2.RadialView

  • RadialView 是另一个尾随组件,用于使 GameObject 的特定部分保持在用户视野的圆锥体内。 “Min和Max View Degrees”属性决定了 GameObject 必须始终在视线范围内的部分的面积。 “Min和Max Distance”属性决定了 GameObject 应该与用户保持多远距离。 例如,如果“Min Distance”为 1 米,走向 GameObject 会将 GameObject 推开,以确保它永远不会距离用户短于 1 米。 通常,RadialView 与设置为 Head 的“TrackedTargetType(跟踪目标类型)”一起使用,这样组件就会跟随用户凝视。 但是,此组件可以发挥作用,以保持在任何跟踪目标类型的“视线”范围内。

5.3.Follow

  • Follow 类将元素定位在跟踪目标的前面,相对于其局部前向轴。 该元素可以是松散约束型(也称为“尾随”),这可以确保在跟踪目标移动到用户定义的边界之外之前它不会跟随。 它的工作方式类似于 RadialView 求解器,但具有更多控制,可以管理“Max View Horizontal和Vertical Degrees(最大水平和垂直视场角度)”,此外还有用于更改对象“方向”的机制

5.4.InBetween

  • InBetween 类使附加的 GameObject 保持在两个转换之间。 这两个转换终结点由 GameObject 自己的 SolverHandlerTrackedTargetType(跟踪目标类型)”和 InBetween 组件的“第二个跟踪目标类型”属性定义。 通常,这两个类型都将设置为 CustomOverride,产生的 SolverHandler.TransformOverrideInBetween.SecondTransformOverride 值将设置为两个跟踪的终结点。 在运行时,InBetween 组件将基于“第二个跟踪目标类型”和“第二个转换覆盖”属性再创建一个 SolverHandler 组件。 PartwayOffset 定义将在直线上两个转换之间的哪个位置放置对象,0.5 表示中间,1.0 表示第一个转换,0.0 表示第二个转换。

5.5.SurfaceMagnetism

  • SurfaceMagnetism 的工作方式是对一组表面的 LayerMask 执行光线投射,并将 GameObject 放置在接触点。“Surface Ray Offset(表面垂直偏移)”按照设定好的距离表面的距离(米),沿着表面上击中点处的法线方向放置 GameObject。相反,“Surface Ray Offset(表面射线偏移)”按照设定好的距离表面的距离(米),沿着所执行光线投射的相反方向放置 GameObject。 因此,如果光线投射是用户凝视的方向,则 GameObject 将沿直线从表面上的击中点向摄像头靠近。
  • Oriention Mode(方向模式)”确定相对于表面上的法线应用的旋转类型。
    • None(无) - 不应用旋转
    • Tracked Target(跟踪目标) - 对象将面向驱动光线投射的跟踪转换
    • Surface Normal(表面法线) - 对象将基于表面上的击中点对齐
    • Blended(混合) - 对象将基于表面上的击中点对齐,并且面向跟踪转换。
  • 要强制关联的 GameObject 在除“None”以外的任何模式下都保持垂直,请启用“Keep Orientation Vertical(使方向保持垂直)”。

5.6 Overlap

  • Overlap是一个简单的求解器,它将使对象的转换保持与转换目标相同的位置和旋转SolverHandler’s

5.7 SurfaceMagnetism

  • SurfaceMagnetism 组件添加到 GameObject 时,必须考虑 GameObject 及其子代的层(如果任何子代有碰撞器)。 该组件的工作方式是执行各种光线投射,以确定哪些表面可以“吸附”光线。 假设求解器 GameObject 在 SurfaceMagnetismMagneticSurfaces 属性所列的其中一个层上有碰撞器。 在这种情况下,光线投射很可能会击中自己,导致 GameObject 附加到其自己的碰撞器点。 这种异常行为是可以避免的,方法是将主 GameObject 和所有子代设置为“忽略光线投射”层或相应地修改 MagneticSurfaces LayerMask 数组。
  • 相反,SurfaceMagnetism GameObject 不会与 MagneticSurfaces 属性中未列出的层上的表面发生碰撞。 建议将所有需要的表面放在专用层(即图面)上,并将 MagneticSurfaces 属性设置为仅此层。 使用“默认”或“全部”可能会导致 UI 组件或光标影响求解器。
  • 最后,SurfaceMagnetism 光线投射将忽略 MaxRaycastDistance 属性设置,而不是表面。

5.8 DirectionalIndicator

  • DirectionalIndicator 类是一个尾随组件,它可以根据空间中指定点的方向调整自身方向。 最常用于 SolverHandler 的“跟踪目标类型”设置为 Head 的情况。 这样,具有 DirectionalIndicator 求解器的 UX 组件将指引用户看空间中的指定点。 此点由 Directional Target 属性确定。
  • 如果用户可以查看方向目标,或在 SolverHandler 中设置了任何参照帧,则该求解器将禁用它下面的所有 Renderer 组件。 如果不可查看,则该指示器上将启用所有内容。 随着用户逐渐靠近以在他们的 FOV 中捕捉“Direction Target(方向目标)”,指示器的大小将缩小。
    • Min Indicator Scale(最小指示器比例) - 指示器对象的最小比例
    • Max Indicator Scale(最大指示器比例) - 指示器对象的最大比例
    • Visibility Scale Factor(可见性比例因子) - 用于增加或减少 FOV 的乘数,用于确定“方向目标”点是否可见
    • View Offset(视角偏移) - 从参考系(可能是相机)的角度来看,该属性定义对象在指示器方向上距视区中心多远。

5.9 HandConstraint 和 HandConstraintPalmUp 的手部菜单

  • HandConstraint 行为提供了一个求解器,该求解器将跟踪对象约束在确保可显示手部约束内容(如手部 UI、菜单等)的区域内。安全区域是指不会与手部相交的区域。 还包含了一个名为 HandConstraintPalmUpHandConstraint 派生类,用于演示手掌朝向用户时激活求解器的常见行为。

0 人点赞