解算器 — MRTK3

規劃求解主要

解算器是一些元件,可協助根據預先定義的演算法來計算物件的位置和方向。 範例:將物件放在使用者注視光線傳播與交集的表面上。

規劃求解系統會決定性地定義這些轉換計算的作業順序,因為沒有可靠的方法可指定給 Unity 元件的更新順序。

解算器提供一系列的行為,以將物件附加至其他物件或系統。 另一個範例是標記物件,該對象會根據相機將滑鼠停留在使用者前面。 規劃求解也可以附加至控制器和 物件,讓對象標記沿著控制器。 所有解算器都可以安全地堆疊,例如卷標行為加上表面磁力加上動量。

如何使用

規劃求解系統包含三種文稿類別:

  • Solver:所有解算器衍生自的抽象基類。 它提供狀態追蹤、平滑參數和實作、自動規劃求解系統整合,以及更新順序。
  • SolverHandler:根據 (範例設定參照對象追蹤:主要相機轉換、手部光線等 ) 、處理規劃求解元件的收集,並依適當順序執行更新它們。

第三個類別是求解器本身。 下列解算器提供基本行為的建置組塊:

  • Orbital:鎖定所參考物件的指定位置和位移。
  • ConstantViewSize:縮放以維護相對於參考物件的檢視的常數大小。
  • RadialView:將物件保留在參考物件所轉換的檢視圓錐內。
  • Follow:將 物件保留在參考物件的一組使用者定義界限內。
  • InBetween:將物件保留在兩個追蹤的對象之間。
  • SurfaceMagnetism:將光線轉換成世界表面,並將對象對齊該表面。
  • DirectionalIndicator:決定物件的位置和方向做為方向指標。 從 SolverHandler Tracked Target 的參考點,此指標會導向所提供的 DirectionalTarget。
  • Momentum:套用加速/速度/摩擦,以模擬由其他求解器/元件移動之對象的動量和彈性。
  • HandConstraint:在不會與 GameObject 交集的區域中追蹤手部的條件約束物件。 適用於手部限制的互動式內容,例如功能表等。此規劃求解旨在使用 XRNode
  • HandConstraintPalmUp:衍生自 HandConstraint,但包含邏輯,以測試手掌是否在啟用前面向使用者。 此規劃求解只適用於 XRNode 控制器,其行為就像其基類與其他控制器類型一樣。
  • Overlap:重迭追蹤的物件。

若要使用規劃求解系統,請將上述其中一個元件新增至 GameObject。 由於所有解算器都需要 SolverHandler,因此 Unity 會自動建立一個。

注意

您可以在 SolverExamples.scene 檔案中找到如何使用解算器系統的範例。

如何變更追蹤參考

元件的 [追蹤目標類型] 屬性 SolverHandler 會定義所有解算器將用來計算其演算法的參考點。 例如,具有簡單SurfaceMagnetism元件的 實值類型Head會導致從頭部和用戶注視的方向投射光線,以解決所點擊的表面。 屬性的 TrackedTargetType 可能值為:

  • *前端:參考點是主相機的轉換
  • ControllerRay:參照 LinePointer 點是控制器 (上的轉換,也就是動作控制器或手部控制器上的指標原點) 指向線條光線的方向
    • TrackedHandedness使用 屬性來選取手部喜好設定 (,也就是 Left、Right、Both)
  • HandJoint:參考點是特定手部聯合的轉換
    • TrackedHandedness使用 屬性來選取手部喜好設定 (,也就是 Left、Right、Both)
    • TrackedHandJoint使用屬性來判斷要使用的聯合轉換
  • CustomOverride:從指派的參考點 TransformOverride

注意

針對 ControllerRayHandJoint 類型,規劃求解處理程式會先嘗試提供左控制器/手轉換,如果前者無法使用,或除非 TrackedHandedness 屬性另有指定,否則會嘗試向右提供。

重要

大部分的解算器會使用 所 SolverHandler提供之追蹤轉換目標的正向向量。 使用 手部聯合 追蹤的目標類型時,手部聯合的正向向量可能會指向手指,而不是透過手掌。 這取決於提供手部聯合數據的平臺。 針對輸入模擬和 Windows Mixed Reality,向上向量會指向手掌 (,換句話說,綠色向量會向上,藍色向量會向前) 。

若要克服這個問題,請將 上的 SolverHandler[其他旋轉] 屬性更新為<90、0、0>。 這可確保提供給解算器的正向向量指向手掌,並向外向外。

或者,使用 控制器 Ray 追蹤的目標類型來取得類似行為來指向手部。

如何鏈結求解器

可以將多個 Solver 元件新增至相同的 GameObject,進而鏈結其演算法。 元件 SolverHandler 會處理更新相同 GameObject 上的所有解算器。 根據預設, SolverHandler Start 上的呼叫 GetComponents<Solver>() 會依照求解器出現在偵測器中的順序傳回。

此外,將 [已更新的鏈接轉換 ] 屬性設定為 true 會指示 Solver 將計算位置、方向和小數位數儲存到所有求解器 (可存取的中繼變數, GoalPosition) 。 若為 false,則會 Solver 直接更新 GameObject 的轉換。 藉由將轉換屬性儲存至中繼位置,其他求解器可以從中繼變數開始執行其計算。 這是因為 Unity 不允許更新 gameObject.transform,以在相同的框架內堆疊。

注意

開發人員可以直接設定 SolverHandler.Solvers 屬性來修改解算器的執行順序。

如何建立新的規劃求解器

所有解算器都必須繼承自抽象基類 。 Solver 規劃求解延伸模組的主要需求涉及覆 SolverUpdate 寫 方法。 在此方法中,開發人員應該將繼承 GoalPosition的、 GoalRotationGoalScale 屬性更新為所需的值。 此外,利用 SolverHandler.TransformTarget 作為取用者所需的參考框架會很有用。

下列程式代碼提供名為 InFront 的新規劃求解元件範例,將附加物件 2 m 放在 前面 SolverHandler.TransformTarget。 取用者會將 設定 SolverHandler.TrackedTargetTypeHead,然後 SolverHandler.TransformTarget 會是相機轉換,因此此規劃求解會將附加的 GameObject 2 m 放在使用者注視的每個畫面前面。

/// <summary>
/// InFront solver positions an object 2m in front of the tracked transform target
/// </summary>
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;
        }
    }
}

規劃求解實作指南

常見的規劃求解屬性

每個規劃求解元件都有一組相同的核心屬性,可控制核心規劃求解行為。

如果已啟用 Smoothing ,規劃求解將會隨著時間逐漸將GameObject的轉換更新為計算值。 每個轉換元件的 LerpTime 屬性都會決定這項變更的速度。 例如,較高的 MoveLerpTime 值會導致畫面之間的移動速度變慢。

如果已啟用 MaintainScale ,規劃求解會利用GameObject的預設本機小數字數。

軌道

類別 Orbital 是沿著卷標的元件,其行為類似於太陽能系統中的行星。 此規劃求解可確保附加的 GameObject 繞著追蹤轉換的軌道。 因此,如果的 SolverHandler[追蹤目標類型] 設定為 Head,則 GameObject 會繞著套用固定位移的用戶頭部。

開發人員可以修改這個固定位移,在用戶周圍保留功能表或其他場景元件,或是在眼睛層級或其他場景元件。 這是藉由變更 Local OffsetWorld Offset 屬性來完成。 Orientation Type 屬性會決定套用至物件的旋轉,如果對象應該維持其原始旋轉,或一律面對相機或面對任何轉換正在驅動其位置。

RadialView

RadialView是另一個標記元件,會在用戶檢視的 frustum 內保留 GameObject 的特定部分。

Min & Max View Degrees 屬性會決定 GameObject 的部分一律必須位於檢視中。

Min & 最大距離屬性會決定 GameObject 應該與使用者保持距離。 例如,以 最小距離 1 公尺前往 GameObject,將 GameObject 推開,以確保它永遠不會比使用者更接近 1 公尺。

一般而言,會RadialView與設定Head的追蹤目標類型搭配使用,讓元件遵循使用者的注視。 不過,此元件可以運作,以保留在任何追蹤目標類型的「檢視」中。

追隨

類別 Follow 會將專案置於追蹤目標前方,相對於其本機正向軸。 元素可以鬆散限制 (也稱為「標籤沿著」) ,因此在追蹤的目標移至超出使用者定義的界限之前,不會追蹤它。

它的運作方式與RadialView規劃求解類似,另外還有一些控件可管理 最大水準 & 垂直檢視度 ,以及改變物件 方向的機制。

InBetween

類別 InBetween 會在兩個轉換之間保留附加的 GameObject。 GameObject 自己的 SolverHandler追蹤目標類型 ,而 InBetween 元件的第 二個追蹤目標類型 屬性會定義這兩個轉換端點。 一般而言,這兩種類型都會設定為 CustomOverride ,而產生的 SolverHandler.TransformOverrideInBetween.SecondTransformOverride 值會設定為兩個追蹤的端點。

元件InBetween會根據第二個追蹤的目標類型和第二個轉換覆寫屬性,在運行時間建立另一個SolverHandler元件。

沿著兩個轉換之間的這一行,定義 PartwayOffset 物件將放置於0.5作為半角的位置、第一個轉換的1.0,以及第二個轉換的0.0。

SurfaceMagnetism

的運作 SurfaceMagnetism 方式是針對一組表面的 LayerMask 執行光線廣播,並將 GameObject 放在該接觸點。

Surface 一般位移會將 GameObject 設定距離放在表面的正常點上,距離表面的距離以公尺為單位。

相反地, Surface Ray Offset 會將 GameObject 放在距離表面的公尺距離,但相對於所執行光線廣播的方向。 因此,如果 raycast 是使用者的注視,GameObject 會沿著表面的點擊點往近移動至相機。

方向模式會決定要套用的旋轉類型,以相對於表面的一般。

  • - 未套用旋轉
  • TrackedTarget - 物件會面臨驅動光線廣播的追蹤轉換
  • SurfaceNormal - 對象會根據表面上點擊點的一般對齊
  • Blended - 對象會根據表面的正常點對齊,並根據追蹤的轉換來對齊。

若要強制相關聯的 GameObject 在 None 以外的任何模式中保持垂直,請啟用 [保留方向垂直]。

注意

當方向模式設定為 Blended 時,使用 Orientation Blend 屬性來控制旋轉因數之間的平衡。 值為 0.0 的方向完全由 TrackedTarget 模式驅動,而 1.0 的值則完全由 SurfaceNormal 驅動方向。

重疊

Overlap是簡單的規劃求解,可將對象的轉換保留在與轉換目標相同的位置和旋轉SolverHandler's位置。

判斷可叫用哪些表面

將元件新增 SurfaceMagnetism 至 GameObject 時,如果有任何衝突器,請務必考慮 GameObject 及其子系的圖層。 元件的運作方式是執行各種光線廣播,以判斷要針對哪個表面「磁力」本身。 假設規劃求解 GameObject 在 屬性SurfaceMagnetism所列MagneticSurfaces的其中一個層次上具有碰撞器。 在此情況下,Raycast 可能會自行叫用,導致 GameObject 附加至它自己的碰撞點。 您可以藉由將主要 GameObject 和所有子系設定為 Ignore Ray 轉換 層或修改 MagneticSurfaces LayerMask 陣列,以避免這種奇數行為。

相反地, SurfaceMagnetism GameObject 不會與屬性中 MagneticSurfaces 未列出的圖層表面碰撞。 建議您將所有所需的表面放在專用層 (,也就是 Surfaces) ,並將 屬性設定 MagneticSurfaces 為僅此圖層。 使用 預設所有專案 可能會導致UI元件或數據指標參與規劃求解。

最後,光播將會忽略SurfaceMagnetismMaxRaycastDistance屬性設定還要遠的表面。

DirectionalIndicator

類別是標籤沿著元件,會將 DirectionalIndicator 本身導向至空間中所需點的方向。 當的SolverHandler追蹤目標類型設定Head為 時,最常使用。 如此一來,具有規劃求解的 DirectionalIndicator UX元件會引導使用者查看所需的空間點。 這個點是由 方向目標 屬性決定。

如果用戶可檢視方向目標,或在 中 SolverHandler設定參考範圍,則此規劃求解會停用其下的所有 Renderer 元件。 如果無法檢視,則會在指標上啟用所有專案。

指標的大小會縮小使用者越接近,就是在其FOV中擷取 方向目標

  • 最小指標小 數位數 - 指針對象的最小小數字數

  • 最大指標小數位數 - 指針對象的最大小數字數

  • 可見度縮放因數 - 乘數以增加或減少FOV,以判斷 方向目標 點是否可檢視

  • 檢視位移 - 從參照框架 (的觀點來看,相機可能) 和指標方向,這個屬性會定義物件與檢視區中心之間的距離。

方向指標範例場景 (資產/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)

使用 HandConstraint 和 HandConstraintPalmUp 的手部功能表

HandConstraint 行為提供將追蹤物件限制為安全區域以進行手部限制內容 (例如手部 UI、功能表等 ) 安全區域的規劃求解會被視為與手部沒有交集的區域。 也包含 名為 HandConstraintPalmUpHandConstraint衍生類別,以示範在手部面向用戶時啟用規劃求解追蹤對象的常見行為。

如需使用手部條件約束求解來建立手部功能表的範例,請參閱手部功能表檔