共用方式為


規劃求解概觀 - MRTK2

規劃求解主要

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

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

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

如何使用規劃求解器

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

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

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

  • Orbital:鎖定指定的位置,並從參考的物件位移。
  • ConstantViewSize:縮放以維持相對於參考物件檢視的常數大小。
  • RadialView:讓物件保留在參考物件所轉換的檢視錐內。
  • Follow:將 物件保留在參考物件的一組使用者定義界限內。
  • InBetween:將 物件保留在兩個追蹤對象之間。
  • SurfaceMagnetism:將光線投射到世界表面,並將物件對齊該表面。
  • DirectionalIndicator:決定物件的位置和方向做為方向指標。 從 SolverHandler 追蹤目標參考點開始,此指標會導向提供的 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屬性另有指定,則為右側。

規劃求解追蹤物件與每個 TrackedTargetType 相關聯的各種屬性範例

重要

大部分的解算器都會使用 所 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 的新規劃求解元件範例,該元件會將附加物件 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的預設本機小數字數。

核心規劃求解屬性
所有規劃求解元件繼承的通用屬性

Orbital

類別 Orbital 是一個標記元件,其行為類似於太陽系中的行星。 此規劃求解可確保附加的 GameObject 會在追蹤轉換周圍繞行。 因此,如果的SolverHandler追蹤目標類型設定為 Head,則 GameObject 會以套用固定位移繞著用戶的頭部。

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

Orbital 範例
Orbital 範例

RadialView

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

Min 和 Max View Degrees 屬性會決定 GameObject 的一部分必須一律在檢視中的大小。

Min 和 Max Distance 屬性會決定 GameObject 應該與使用者保持距離。 例如,使用最小距離 1m 的 GameObject 往前走,將 GameObject 推開,以確保它永遠不會比使用者更接近 100 萬。

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

RadialView 範例
RadialView 範例

追隨

類別會將 Follow 專案放置在追蹤目標前面,相對於其本機正向座標軸。 元素可以鬆散地限制(也就是標籤一起),因此在追蹤的目標超出使用者定義界限之前,它才會跟著。

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

追蹤屬性
追蹤屬性

遵循範例場景
遵循範例場景 (Assets/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 範例
使用 InBetween 規劃求解在兩個轉換之間保留物件的範例

SurfaceMagnetism

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

Surface Normal Offset 會將 GameObject 放置在距離表面幾公尺的一定距離上,位於表面命中點的正常方向。

相反地, Surface Ray Offset 會將 GameObject 放在離表面幾米遠的一定距離,但相對於執行光線廣播的方向。 因此,如果光線廣播是使用者的注視,則 GameObject 會沿著線條從表面上的命中點向相機移動。

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

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

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

注意

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

SurfaceMagnetism 範例

判斷可以點擊哪些表面

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

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

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

DirectionalIndicator

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

當的SolverHandler追蹤目標類型設定為 Head時,最常使用。 以這種方式,具有規劃求解的 DirectionalIndicator UX元件會指示使用者查看所需的空間點。

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

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

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

  • 最小指標尺規 - 指針對象的最小尺規

  • 最大指標尺規 - 指針對象的最大尺規

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

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

方向指示器屬性
方向指示器屬性

方向指示器範例場景
方向指標範例場景 (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)

HandConstraint 和 HandConstraintPalmUp 的手部功能表

手部功能表 UX 範例

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

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

另請參閱