規劃求解概觀 - MRTK2

Solver Main

求解器是一些元件,可協助根據預先定義的演算法來計算物件的位置 & 方向。 例如,在使用者注視光線廣播目前點擊的表面上放置物件。

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

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

如何使用規劃求解

規劃求解系統包含三種腳本類別:

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

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

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

若要使用規劃求解系統,只要將上述其中一個元件新增至 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 屬性另有指定,則為右邊。

Solver Tracked Object與每個 TrackedTargetType 相關聯的各種屬性範例

重要

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

Forward Up vector

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

Additional Rotation

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

如何鏈結求解器

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

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

注意

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

如何建立新的規劃求解

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

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

/// <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 的預設本機小數位數。

Core Solver Properties
所有規劃求解元件繼承的通用屬性

軌道

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

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

Orbital Example
Orbital 範例

RadialView

RadialView是另一個標籤元件,可在使用者檢視的 frustum 中保留 GameObject 的特定部分。

最小 & 檢視度屬性會決定 GameObject 部分的大小一律在檢視中。

最小 & 距離屬性會決定 GameObject 應該與使用者保持距離。 例如,前往具有 最小距離 1m 的 GameObject 會將 GameObject 推開,以確保它永遠不會接近使用者 1m。

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

RadialView Example
RadialView 範例

追隨

類別會將 Follow 專案置於追蹤目標相對於其本機正向軸的 前面。 元素可以鬆散限制 (a.k.a.標籤) ,以便在追蹤的目標移至超出使用者定義的界限之前,不會追蹤它。

它的運作方式與 RadialView 規劃求解類似,具有其他控制項來管理 最大水準 & 垂直檢視度,以及改變物件 方向 的機制。

Follow properties
追蹤屬性

Follow example scene
遵循範例場景 (資產/MRTK/Examples/Demos/Solvers/Scenes/FollowSolverExample.unity)

InBetween

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

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

定義 PartwayOffset 物件在兩個轉換之間的行之間,應該將 0.5 放在半形、第一次轉換時為 1.0,而第二個轉換則為 0.0。

InBetween Example
使用 InBetween 規劃求解在兩個轉換之間保留物件的範例

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驅動方向。

SurfaceMagnetism Example

判斷可叫用哪些表面

將元件新增 SurfaceMagnetism 至 GameObject 時,如果有任何碰撞器,請務必考慮 GameObject 及其子系的圖層。 此元件的運作方式是執行各種類型的光線傳播,以判斷要「磁力」本身的介面。 如果規劃求解 GameObject 在 屬性 SurfaceMagnetism 所列 MagneticSurfaces 的其中一個圖層上有一個碰撞器,則光線傳播可能會自行點擊,導致 GameObject 附加至自己的碰撞器點。 您可以將主要 GameObject 和所有子系設定為 Ignore Raycast 圖層或修改 MagneticSurfaces LayerMask 陣列,以避免這種奇數行為。

相反地, SurfaceMagnetism GameObject 不會與屬性中 MagneticSurfaces 未列出的圖層表面衝突。 通常建議您將所有所需的表面放在專用層 (,也就是 Surfaces) ,並將 屬性設定 MagneticSurfaces 為僅此圖層。 使用 預設所有專案 可能會導致 UI 元件或資料指標造成求解器。

最後,光線傳播將會忽略比屬性設定更 MaxRaycastDistance 遠的 SurfaceMagnetism 表面。

DirectionalIndicator

類別 DirectionalIndicator 是標記元件,會將本身導向至所需空間點的方向。

當 的 SolverHandler追蹤目標型別設定為 Head 時,最常使用。 如此一來,具有規劃求解的 DirectionalIndicator UX 元件會引導使用者查看所需的空間點。

所需的空間點是透過 方向目標 屬性來決定。

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

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

  • 最小指標小數位數 - 指標物件的最小小數位數

  • 最大指標小數位數 - 指標物件的最大小數位數

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

  • 檢視位移 - 從參照框架的觀點 (例如相機可能) ,此屬性會定義物件應該從檢視區中央到指標方向的距離。

Directional Indicator properties
方向指示器屬性

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

具有 HandConstraint 和 HandConstraintPalmUp 的手部功能表

Hand Menu UX Example

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

如需使用手部條件約束規劃求解來建立手部功能表的範例,請參閱 [手部功能表] 頁面。

另請參閱