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

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


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 米处。
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 派生类,用于演示手掌朝向用户时激活求解器的常见行为。
相关文章
|
4月前
|
算法 vr&ar C#
使用Unity进行虚拟现实开发:深入探索与实践
【8月更文挑战第24天】使用Unity进行虚拟现实开发是一个充满挑战和机遇的过程。通过掌握Unity的VR开发技术,你可以创造出令人惊叹的VR体验,为用户带来前所未有的沉浸感和乐趣。随着技术的不断进步和应用场景的不断拓展,VR开发的未来充满了无限可能。希望本文能为你提供有用的指导和启发!
|
3月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
291 0
|
3月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
159 0
|
4月前
|
vr&ar 图形学 开发者
步入未来科技前沿:全方位解读Unity在VR/AR开发中的应用技巧,带你轻松打造震撼人心的沉浸式虚拟现实与增强现实体验——附详细示例代码与实战指南
【8月更文挑战第31天】虚拟现实(VR)和增强现实(AR)技术正深刻改变生活,从教育、娱乐到医疗、工业,应用广泛。Unity作为强大的游戏开发引擎,适用于构建高质量的VR/AR应用,支持Oculus Rift、HTC Vive、Microsoft HoloLens、ARKit和ARCore等平台。本文将介绍如何使用Unity创建沉浸式虚拟体验,包括设置项目、添加相机、处理用户输入等,并通过具体示例代码展示实现过程。无论是完全沉浸式的VR体验,还是将数字内容叠加到现实世界的AR应用,Unity均提供了所需的一切工具。
156 0
|
6月前
|
C# 图形学 C++
使用vscode开发C#+unity没有代码提示问题
使用vscode开发C#+unity没有代码提示问题
96 0
使用vscode开发C#+unity没有代码提示问题
|
6月前
|
图形学
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)
95 0
|
6月前
|
图形学
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏3(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏3(附项目源码)
106 0
|
6月前
|
图形学 索引
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏1(附项目源码)
152 0
|
7月前
|
图形学
【Unity C#_菜单Window开发系列_Inspector Component UnityEditor开发】
【Unity C#_菜单Window开发系列_Inspector Component UnityEditor开发】
|
4月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
220 6