MR Input 213:運動控制器MR Input 213: Motion controllers

注意

混合實境學院教學課程的設計是以 HoloLens (第 1 代) 和混合實境沉浸式頭戴裝置為準。The Mixed Reality Academy tutorials were designed with HoloLens (1st gen) and Mixed Reality Immersive Headsets in mind. 因此,對於仍在尋找這些裝置開發指引的開發人員而言,我們覺得這些教學課程很重要。As such, we feel it is important to leave these tutorials in place for developers who are still looking for guidance in developing for those devices. 這些教學課程 不會 使用用於 HoloLens 2 的最新工具組或互動進行更新。These tutorials will not be updated with the latest toolsets or interactions being used for HoloLens 2. 系統會保留這些資訊,以繼續在支援的裝置上運作。They will be maintained to continue working on the supported devices. 已針對 HoloLens 2 公佈一系列新的教學課程A new series of tutorials has been posted for HoloLens 2.

混合現實世界中的運動控制器會新增另一個層級的互動。Motion controllers in the mixed reality world add another level of interactivity. 有了 運動控制器,我們就能以更自然的方式直接與物件互動,類似于真實生活中的實際互動,在您的應用程式體驗中增加深度和取悅。With motion controllers, we can directly interact with objects in a more natural way, similar to our physical interactions in real life, increasing immersion and delight in your app experience.

在 MR 輸入213中,我們會藉由建立簡單的空間繪製體驗來探索移動控制器的輸入事件。In MR Input 213, we will explore the motion controller's input events by creating a simple spatial painting experience. 使用此應用程式,使用者可以使用各種類型的筆刷和色彩,在三維空間中進行繪製。With this app, users can paint in three-dimensional space with various types of brushes and colors.

本教學課程中涵蓋的主題Topics covered in this tutorial

MixedReality213 Topic1 MixedReality213 Topic2 MixedReality213 Topic3
控制器視覺效果Controller visualization 控制器輸入事件Controller input events 自訂控制器和 UICustom controller and UI
瞭解如何在 Unity 的遊戲模式和執行時間中呈現移動控制器模型。Learn how to render motion controller models in Unity's game mode and runtime. 瞭解不同類型的按鈕事件和其應用程式。Understand different types of button events and their applications. 瞭解如何將 UI 元素重迭在控制器上,或完全自訂。Learn how to overlay UI elements on top of the controller or fully customize it.

裝置支援Device support

課程Course HoloLensHoloLens 沉浸式頭戴裝置Immersive headsets
MR Input 213:運動控制器MR Input 213: Motion controllers ✔️✔️

在您開始使用 Intune 之前Before you start

必要條件Prerequisites

請參閱 此頁面上的沉浸式耳機安裝檢查清單。See the installation checklist for immersive headsets on this page.

專案檔Project files

  • 下載 專案所需的檔案,並將檔案解壓縮至桌面。Download the files required by the project and extract the files to the Desktop.

注意

如果您想要在下載之前查看原始程式碼, 可在 GitHub 上取得。If you want to look through the source code before downloading, it's available on GitHub.

Unity 設定Unity setup

目標Objectives

  • 針對 Windows Mixed Reality 開發優化 UnityOptimize Unity for Windows Mixed Reality development
  • 安裝混合實境相機Setup Mixed Reality Camera
  • 設定環境Setup environment

指示Instructions

  • 啟動 Unity。Start Unity.

  • 選取 [開啟] 。Select Open.

  • 流覽至您的桌面,並尋找您先前 unarchived 的 MixedReality213 主 資料夾。Navigate to your Desktop and find the MixedReality213-master folder you previously unarchived.

  • 按一下 [選擇資料夾]。Click Select Folder.

  • Unity 完成載入專案檔之後,您就能夠看到 Unity 編輯器。Once Unity finishes loading project files, you will be able to see Unity editor.

  • 在 Unity 中,選取 [ File > Build Settings]。In Unity, select File > Build Settings.

    MR213_BuildSettings

  • 在 [平臺] 清單中選取 通用 Windows 平臺,然後按一下 [切換平臺] 按鈕。Select Universal Windows Platform in the Platform list and click the Switch Platform button.

  • 將目標裝置設定為 任何裝置Set Target Device to Any device

  • 將組建類型設定為 D3DSet Build Type to D3D

  • 將 SDK 設定為 最新安裝Set SDK to Latest Installed

  • 檢查 Unity c # 專案Check Unity C# Projects

    • 這可讓您修改 Visual Studio 專案中的指令檔,而不需要重建 Unity 專案。This allows you modify script files in the Visual Studio project without rebuilding Unity project.
  • 按一下 [ 玩家設定]。Click Player Settings.

  • 在 [偵測 ] 面板中,向下滾動至底部In the Inspector panel, scroll down to the bottom

  • 在 [XR 設定] 中,檢查 支援的虛擬實境In XR Settings, check Virtual Reality Supported

  • 在 [虛擬實境 Sdk] 下,選取 Windows Mixed RealityUnder Virtual Reality SDKs, select Windows Mixed Reality

    MR213_XRSettings

  • 關閉 [ 組建設定 ] 視窗。Close Build Settings window.

專案結構Project structure

本教學課程使用 混合現實工具組-UnityThis tutorial uses Mixed Reality Toolkit - Unity. 您可以在 此頁面上找到這些版本。You can find the releases on this page.

ProjectStructure

針對您的參考完成的場景Completed scenes for your reference

  • 您會在 幕後 資料夾中找到兩個已完成的 Unity 幕後。You will find two completed Unity scenes under Scenes folder.
    • MixedReality213:已完成場景與單一筆刷MixedReality213: Completed scene with single brush
    • MixedReality213Advanced:使用多筆刷完成適用于 advanced design 的場景MixedReality213Advanced: Completed scene for advanced design with multiple brushes

教學課程的新場景設定New Scene setup for the tutorial

  • 在 Unity 中,按一下 [檔案] > 新增場景In Unity, click File > New Scene

  • 刪除 主要攝影機方向光線Delete Main Camera and Directional Light

  • 在 [ 專案] 面板 中,搜尋下列 prefabs,並將 其拖曳 到 [階層] 面板中:From the Project panel, search and drag the following prefabs into the Hierarchy panel:

    • 資產/HoloToolkit/Input/Prefabs/MixedRealityCameraAssets/HoloToolkit/Input/Prefabs/MixedRealityCamera
    • 資產/AppPrefabs/環境Assets/AppPrefabs/Environment

    攝影機和環境

  • 混合現實工具組中有兩種攝影機 prefabs:There are two camera prefabs in Mixed Reality Toolkit:

    • MixedRealityCamera. 預製專案:僅限相機MixedRealityCamera.prefab: Camera only
    • MixedRealityCameraParent. 預製專案:相機 + 遙傳 + 界限MixedRealityCameraParent.prefab: Camera + Teleportation + Boundary
    • 在本教學課程中,我們將使用 MixedRealityCamera 而不使用遙傳功能。In this tutorial, we will use MixedRealityCamera without teleportation feature. 因此,我們新增了簡單的 環境 預製專案,其中包含讓使用者感覺更接地的基本樓層。Because of this, we added simple Environment prefab which contains a basic floor to make the user feel grounded.
    • 若要深入瞭解遙傳 with MixedRealityCameraParent,請參閱 Advanced design-遙傳 and locomotionTo learn more about the teleportation with MixedRealityCameraParent, see Advanced design - Teleportation and locomotion

Skybox 設定Skybox setup

  • 按一下 [ 視窗] > 光源 > 設定Click Window > Lighting > Settings

  • 按一下 [ Skybox 材質] 欄位 右邊的圓形Click the circle on the right side of the Skybox Material field

  • 輸入「灰色」並選取 SkyboxGray (資產/AppPrefabs/支援/材質/SkyboxGray) Type in ‘gray’ and select SkyboxGray (Assets/AppPrefabs/Support/Materials/SkyboxGray.mat)

    設定 skybox

  • 檢查 Skybox 選項,以查看指派的灰色漸層 SkyboxCheck Skybox option to be able to see assigned gray gradient skybox

    切換 skybox 選項

  • 具有 MixedRealityCamera、環境和灰色 skybox 的場景看起來會像這樣。The scene with MixedRealityCamera, Environment and gray skybox will look like this.

    MixedReality213 環境

  • 按一下 [檔案] > 另存場景Click File > Save Scene as

  • 以任何名稱 將場景儲存 在場景資料夾下Save your scene under Scenes folder with any name

第1章-控制器視覺效果Chapter 1 - Controller visualization

目標Objectives

  • 瞭解如何在 Unity 的遊戲模式和執行時間轉譯移動控制器模型。Learn how to render motion controller models in Unity's game mode and at runtime.

Windows Mixed Reality 提供適用于控制器視覺效果的動畫控制器模型。Windows Mixed Reality provides an animated controller model for controller visualization. 您可以針對應用程式中的控制器視覺效果採用幾種方法:There are several approaches you can take for controller visualization in your app:

  • 預設-使用預設控制器而不修改Default - Using default controller without modification
  • 混合式使用預設控制器,但自訂其部分元素或覆迭 UI 元件Hybrid - Using default controller, but customizing some of its elements or overlaying UI components
  • 取代-為控制器使用您自己的自訂3D 模型Replacement - Using your own customized 3D model for the controller

在本章中,我們將瞭解這些控制器自訂的範例。In this chapter, we will learn about the examples of these controller customizations.

指示Instructions

  • 在 [ 專案 ] 面板的 [搜尋] 方塊中,輸入 MotionControllersIn the Project panel, type MotionControllers in the search box . 您也可以在 [資產/HoloToolkit/輸入/Prefabs/] 下找到它。You can also find it under Assets/HoloToolkit/Input/Prefabs/.
  • MotionControllers 預製專案拖曳到 [階層 ] 面板中Drag the MotionControllers prefab into the Hierarchy panel.
  • 按一下 [階層 ] 面板中的 [ MotionControllers ] 預製專案。Click on the MotionControllers prefab in the Hierarchy panel.

MotionControllers 預製專案MotionControllers prefab

MotionControllers 預製專案具有 MotionControllerVisualizer 腳本,可提供替代控制器模型的位置。MotionControllers prefab has a MotionControllerVisualizer script which provides the slots for alternate controller models. 如果您指派自己的自訂3D 模型(例如手或寶劍)並核取 [一律使用替代模型],則會看到它們,而不是預設模型。If you assign your own custom 3D models such as a hand or a sword and check 'Always Use Alternate Left/Right Model', you will see them instead of the default model. 我們將在第4章中使用這個位置,以筆刷取代控制器模型。We will use this slot in Chapter 4 to replace the controller model with a brush.

MR213_ControllerVisualizer

指示Instructions

  • 在 [偵測 ] 面板中,按兩下 [ MotionControllerVisualizer 腳本] 以查看 Visual Studio 中的程式碼In the Inspector panel, double click MotionControllerVisualizer script to see the code in the Visual Studio

MotionControllerVisualizer 腳本MotionControllerVisualizer script

MotionControllerVisualizerMotionControllerInfo 類別提供存取 & 修改預設控制器模型的方法。The MotionControllerVisualizer and MotionControllerInfo classes provide the means to access & modify the default controller models. MotionControllerVisualizer 會訂閱 Unity 的 InteractionSourceDetected 事件,並且在找到控制器模型時自動將其具現化。MotionControllerVisualizer subscribes to Unity's InteractionSourceDetected event and automatically instantiates controller models when they are found.

protected override void Awake()
{
    ...
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    ...
}

控制器模型是根據 glTF 規格來傳遞。The controller models are delivered according to the glTF specification. 這種格式的建立是為了提供通用格式,同時改進了傳輸和解除包裝3D 資產的程式。This format has been created to provide a common format, while improving the process behind transmitting and unpacking 3D assets. 在此情況下,我們需要在執行時間取出和載入控制器模型,因為我們想要讓使用者的體驗盡可能順暢,而且不保證使用者可能使用的動作控制器版本。In this case, we need to retrieve and load the controller models at runtime, as we want to make the user's experience as seamless as possible, and it's not guaranteed which version of the motion controllers the user might be using. 此課程透過混合現實工具組,使用 Khronos 群組的 UnityGLTF 專案版本。This course, via the Mixed Reality Toolkit, uses a version of the Khronos Group's UnityGLTF project.

一旦傳遞控制器,腳本就可以使用 MotionControllerInfo 來尋找特定控制器元素的轉換,讓它們可以正確地定位。Once the controller has been delivered, scripts can use MotionControllerInfo to find the transforms for specific controller elements so they can correctly position themselves.

在稍後的章節中,我們將瞭解如何使用這些腳本,將 UI 元素附加至控制器。In a later chapter, we will learn how to use these scripts to attach UI elements to the controllers.

在某些腳本中,您會發現具有 #if 的程式碼區塊 !UNITY_EDITORUNITY_WSA。這些程式碼區塊只會在您部署至 Windows 時于 UWP 執行時間上執行。這是因為 Unity 編輯器和 UWP 應用程式執行時間所使用的 Api 集不同。In some scripts, you will find code blocks with #if !UNITY_EDITOR or UNITY_WSA. These code blocks run only on the UWP runtime when you deploy to Windows. This is because the set of APIs used by the Unity editor and the UWP app runtime are different.

  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button.

您將能夠在耳機中看到有移動控制器的場景。You will be able to see the scene with motion controllers in your headset. 您可以看到按鈕點擊、操縱杆移動和觸控板觸控醒目提示的詳細動畫。You can see detailed animations for button clicks, thumbstick movement, and touchpad touch highlighting.

MR213_Controller 視覺效果預設

第2章-將 UI 元素附加至控制器Chapter 2 - Attaching UI elements to the controller

目標Objectives

  • 瞭解動作控制器的元素Learn about the elements of the motion controllers
  • 瞭解如何將物件附加至控制器的特定部分Learn how to attach objects to specific parts of the controllers

在本章中,您將瞭解如何將使用者介面專案新增至控制器,讓使用者隨時都能輕鬆地存取和操作。In this chapter, you will learn how to add user interface elements to the controller which the user can easily access and manipulate at anytime. 您也將瞭解如何使用觸控板輸入來新增簡單的色彩選擇器 UI。You will also learn how to add a simple color picker UI using the touchpad input.

指示Instructions

  • 在 [ 專案 ] 面板中,搜尋 MotionControllerInfo 腳本。In the Project panel, search MotionControllerInfo script.
  • 從搜尋結果中,按兩下 [ MotionControllerInfo 腳本] 以查看 Visual Studio 中的程式碼。From the search result, double click MotionControllerInfo script to see the code in Visual Studio.

MotionControllerInfo 腳本MotionControllerInfo script

第一個步驟是選擇您要讓 UI 附加至哪個控制器元素。The first step is to choose which element of the controller you want the UI to attach to. 這些元素是在 MotionControllerInfo.csControllerElementEnum 中定義。These elements are defined in ControllerElementEnum in MotionControllerInfo.cs.

MR213 MotionControllerElements

  • 首頁Home
  • 功能表Menu
  • 把握Grasp
  • 操縱杆Thumbstick
  • 選取Select
  • 觸控板Touchpad
  • 指標姿勢 –此元素表示控制器指向正向方向的秘訣。Pointing pose – this element represents the tip of the controller pointing forward direction.

指示Instructions

  • 在 [ 專案 ] 面板中,搜尋 AttachToController 腳本。In the Project panel, search AttachToController script.
  • 從搜尋結果中,按兩下 [ AttachToController 腳本] 以查看 Visual Studio 中的程式碼。From the search result, double click AttachToController script to see the code in Visual Studio.

AttachToController 腳本AttachToController script

AttachToController 腳本提供簡單的方式,將任何物件附加至指定的控制器 handedness 和元素。The AttachToController script provides a simple way to attach any objects to a specified controller handedness and element.

AttachElementToController ( # B1 中,In AttachElementToController(),

  • 使用 MotionControllerInfo. handedness 檢查 handednessCheck handedness using MotionControllerInfo.Handedness
  • 使用 MotionControllerInfo. TryGetElement 取得控制器的特定元素 ( # B1Get specific element of the controller using MotionControllerInfo.TryGetElement()
  • 從控制器模型中抓取專案的轉換之後,父物件下的物件和設定物件的本機位置 & 旋轉為零。After retrieving the element's transform from the controller model, parent the object under it and set object's local position & rotation to zero.
public MotionControllerInfo.ControllerElementEnum Element { get { return element; } }

private void AttachElementToController(MotionControllerInfo newController)
{
     if (!IsAttached && newController.Handedness == handedness)
     {
          if (!newController.TryGetElement(element, out elementTransform))
          {
               Debug.LogError("Unable to find element of type " + element + " under controller " + newController.ControllerParent.name + "; not attaching.");
               return;
          }

          controller = newController;

          SetChildrenActive(true);

          // Parent ourselves under the element and set our offsets
          transform.parent = elementTransform;
          transform.localPosition = positionOffset;
          transform.localEulerAngles = rotationOffset;
          if (setScaleOnAttach)
          {
               transform.localScale = scale;
          }

          // Announce that we're attached
          OnAttachToController();
          IsAttached = true;
     }
}

使用 AttachToController 腳本最簡單的方式就是從它繼承,如同我們在 ColorPickerWheel 的案例中所做的一樣 The simplest way to use AttachToController script is to inherit from it, as we've done in the case of ColorPickerWheel. 只要覆寫 OnAttachToControllerOnDetachFromController 函式,就可以在偵測到控制器/中斷連線時執行您的設定/細目。Simply override the OnAttachToController and OnDetachFromController functions to perform your setup / breakdown when the controller is detected / disconnected.

指示Instructions

  • 在 [ 專案 ] 面板中,輸入搜尋方塊 ColorPickerWheelIn the Project panel, type in the search box ColorPickerWheel. 您也可以在 [資產/AppPrefabs/] 下找到它。You can also find it under Assets/AppPrefabs/.
  • ColorPickerWheel 預製專案拖曳到 [階層 ] 面板中。Drag ColorPickerWheel prefab into the Hierarchy panel.
  • 按一下 [階層 ] 面板中的 [ ColorPickerWheel ] 預製專案。Click the ColorPickerWheel prefab in the Hierarchy panel.
  • 在 [偵測 ] 面板中,按兩下 [ ColorPickerWheel 腳本] 以查看 Visual Studio 中的程式碼。In the Inspector panel, double click ColorPickerWheel Script to see the code in Visual Studio.

ColorPickerWheel 預製專案

ColorPickerWheel 腳本ColorPickerWheel script

因為 ColorPickerWheel 會繼承 AttachToController,所以它會在 [偵測 ] 面板中顯示 Handedness元素Since ColorPickerWheel inherits AttachToController, it shows Handedness and Element in the Inspector panel. 我們會將 UI 附加至左方控制器上的「觸控板」元素。We'll be attaching the UI to the Touchpad element on the left controller.

ColorPickerWheel 腳本

ColorPickerWheel 會覆寫 OnAttachToControllerOnDetachFromController ,以訂閱將在下一章中用來選取觸控板輸入之色彩的輸入事件。ColorPickerWheel overrides the OnAttachToController and OnDetachFromController to subscribe to the input event which will be used in next chapter for color selection with touchpad input.

public class ColorPickerWheel : AttachToController, IPointerTarget
{
    protected override void OnAttachToController()
    {
        // Subscribe to input now that we're parented under the controller
        InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
    }

    protected override void OnDetachFromController()
    {
        Visible = false;

        // Unsubscribe from input now that we've detached from the controller
        InteractionManager.InteractionSourceUpdated -= InteractionSourceUpdated;
    }
    ...
}
  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button.

將物件附加至控制器的替代方法Alternative method for attaching objects to the controllers

建議您的腳本繼承自 AttachToController 並覆寫 OnAttachToControllerWe recommend that your scripts inherit from AttachToController and override OnAttachToController. 不過,這可能不一定可行。However, this may not always be possible. 替代方法是使用它作為獨立元件。An alternative is using it as a standalone component. 當您想要在不重構腳本的情況下,將現有的預製專案附加至控制器時,這會很有用。This can be useful when you want to attach an existing prefab to a controller without refactoring your scripts. 您只需在執行任何安裝程式之前,讓您的類別等待 IsAttached 設為 true。Simply have your class wait for IsAttached to be set to true before performing any setup. 最簡單的方法是使用協同程式作為「開始」。The simplest way to do this is by using a coroutine for 'Start.'

private IEnumerator Start() {
    AttachToController attach = gameObject.GetComponent<AttachToController>();

    while (!attach.IsAttached) {
        yield return null;
    }

    // Perform setup here
}

第3章-使用觸控板輸入Chapter 3 - Working with touchpad input

目標Objectives

  • 瞭解如何取得觸控板輸入資料事件Learn how to get touchpad input data events
  • 瞭解如何為您的應用程式體驗使用觸控板軸位置資訊Learn how to use touchpad axis position information for your app experience

指示Instructions

  • 在 [階層] 面板中,按一下 [ ColorPickerWheel ]In the Hierarchy panel, click ColorPickerWheel
  • 在 [偵測 ] 面板的 [ Animator] 底下,按兩下 [ ColorPickerWheelController ]In the Inspector panel, under Animator, double click ColorPickerWheelController
  • 您將能夠看到開啟的 Animator 索引標籤You will be able to see Animator tab opened

使用 Unity 的動畫控制器顯示/隱藏 UIShowing/hiding UI with Unity's Animation controller

若要使用動畫來顯示及隱藏 ColorPickerWheel UI,我們會使用 Unity 的動畫系統To show and hide the ColorPickerWheel UI with animation, we are using Unity's animation system. ColorPickerWheelVisible 屬性設定為 true 或 false 時,觸發程式會 顯示隱藏 動畫觸發程式。Setting the ColorPickerWheel's Visible property to true or false triggers Show and Hide animation triggers. 顯示隱藏 參數定義于 ColorPickerWheelController 動畫控制器中。Show and Hide parameters are defined in the ColorPickerWheelController animation controller.

Unity 動畫控制器

指示Instructions

  • 在 [階層] 面板中,選取 [ ColorPickerWheel 預製專案In the Hierarchy panel, select ColorPickerWheel prefab
  • 在 [偵測 ] 面板中,按兩下 [ ColorPickerWheel 腳本] 以查看 Visual Studio 中的程式碼In the Inspector panel, double click ColorPickerWheel script to see the code in the Visual Studio

ColorPickerWheel 腳本ColorPickerWheel script

ColorPickerWheel 訂閱 Unity 的 InteractionSourceUpdated 事件以接聽觸控板事件。ColorPickerWheel subscribes to Unity's InteractionSourceUpdated event to listen for touchpad events.

InteractionSourceUpdated ( # B1 中,腳本會先檢查以確定它:In InteractionSourceUpdated(), the script first checks to ensure that it:

  • 實際上是 (obj 的「觸控板」事件。touchpadTouched) is actually a touchpad event (obj.state.touchpadTouched)
  • 源自左方控制器 (的 obj。handedness) originates from the left controller (obj.state.source.handedness)

如果兩者都是 true,表示觸控板位置 (obj。touchpadPosition) 會指派給 selectorPositionIf both are true, the touchpad position (obj.state.touchpadPosition) is assigned to selectorPosition.

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness && obj.state.touchpadTouched)
    {
        Visible = true;
        selectorPosition = obj.state.touchpadPosition;
    }
}

Update ( # B1 中,根據 visible 屬性,它會觸發在色彩選擇器的 animator 元件中顯示和隱藏動畫觸發程式In Update(), based on visible property, it triggers Show and Hide animation triggers in the color picker's animator component

if (visible != visibleLastFrame)
{
    if (visible)
    {
        animator.SetTrigger("Show");
    }
    else
    {
        animator.SetTrigger("Hide");
    }
}

Update ( # B1 中, selectorPosition 是用來將光線轉換成色輪的網格碰撞器,它會傳回一個 UV 位置。In Update(), selectorPosition is used to cast a ray at the color wheel's mesh collider, which returns a UV position. 然後,您可以使用這個位置來尋找色輪材質的圖元座標和色彩值。This position can then be used to find the pixel coordinate and color value of the color wheel's texture. 透過 SelectedColor 屬性可存取其他腳本的這個值。This value is accessible to other scripts via the SelectedColor property.

色彩選擇器滾輪 Raycasting

...
    // Clamp selector position to a radius of 1
    Vector3 localPosition = new Vector3(selectorPosition.x * inputScale, 0.15f, selectorPosition.y * inputScale);
    if (localPosition.magnitude > 1)
    {
        localPosition = localPosition.normalized;
    }
    selectorTransform.localPosition = localPosition;

    // Raycast the wheel mesh and get its UV coordinates
    Vector3 raycastStart = selectorTransform.position + selectorTransform.up * 0.15f;
    RaycastHit hit;
    Debug.DrawLine(raycastStart, raycastStart - (selectorTransform.up * 0.25f));

    if (Physics.Raycast(raycastStart, -selectorTransform.up, out hit, 0.25f, 1 << colorWheelObject.layer, QueryTriggerInteraction.Ignore))
    {
        // Get pixel from the color wheel texture using UV coordinates
        Vector2 uv = hit.textureCoord;
        int pixelX = Mathf.FloorToInt(colorWheelTexture.width * uv.x);
        int pixelY = Mathf.FloorToInt(colorWheelTexture.height * uv.y);
        selectedColor = colorWheelTexture.GetPixel(pixelX, pixelY);
        selectedColor.a = 1f;
    }
    // Set the selector's color and blend it with white to make it visible on top of the wheel
    selectorRenderer.material.color = Color.Lerp (selectedColor, Color.white, 0.5f);
}

第4章-覆寫控制器模型Chapter 4 - Overriding controller model

目標Objectives

  • 瞭解如何使用自訂3D 模型覆寫控制器模型。Learn how to override the controller model with a custom 3D model.

MR213_BrushToolOverride

指示Instructions

  • 按一下 [階層] 面板中的 [ MotionControllers ]。Click MotionControllers in the Hierarchy panel.
  • 按一下 替代右邊控制器 欄位右邊的圓形。Click the circle on the right side of the Alternate Right Controller field.
  • 輸入 ' BrushController',然後從結果中選取預製專案。Type in 'BrushController' and select the prefab from the result. 您可以在資產/AppPrefabs/BrushController 中找到它。You can find it under Assets/AppPrefabs/BrushController.
  • 勾選 [一律使用替代模型]Check Always Use Alternate Right Model

MR213_BrushToolOverrideSlot

BrushController 預製專案不一定要 包含在階層面板中The BrushController prefab does not have to be included in the Hierarchy panel. 不過,若要簽出其子元件:However, to check out its child components:

  • 在 [ 專案 ] 面板中,輸入 BrushController ,並將 BrushController 預製專案拖曳 到 [階層 ] 面板中。In the Project panel, type in BrushController and drag BrushController prefab into the Hierarchy panel.

MR213_BrushTool_Prefab2

您將會在 BrushController 中找到 Tip 元件。You will find the Tip component in BrushController. 我們會使用其轉換來啟動/停止繪製線條。We will use its transform to start/stop drawing lines.

  • 階層面板中 刪除 BrushControllerDelete the BrushController from the Hierarchy panel.
  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button. 您將能夠看到筆刷模型取代右手邊的移動控制器。You will be able to see the brush model replaced the right-hand motion controller.

第5章-使用選取輸入進行繪製Chapter 5 - Painting with Select input

目標Objectives

  • 瞭解如何使用選取按鈕事件來啟動和停止線條繪圖Learn how to use the Select button event to start and stop a line drawing

指示Instructions

  • 在 [專案] 面板中搜尋 BrushController 預製專案。Search BrushController prefab in the Project panel.
  • 在 [偵測 ] 面板中,按兩下 [ BrushController 腳本] 以查看 Visual Studio 中的程式碼In the Inspector panel, double click BrushController Script to see the code in Visual Studio

BrushController 腳本BrushController script

BrushController 訂閱 InteractionManager 的 InteractionSourcePressedInteractionSourceReleased 事件。BrushController subscribes to the InteractionManager's InteractionSourcePressed and InteractionSourceReleased events. 觸發 InteractionSourcePressed 事件時,筆刷的 Draw 屬性會設定為 true;觸發 InteractionSourceReleased 事件時,筆刷的 Draw 屬性會設定為 false。When InteractionSourcePressed event is triggered, the brush's Draw property is set to true; when InteractionSourceReleased event is triggered, the brush's Draw property is set to false.

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = true;
    }
}

private void InteractionSourceReleased(InteractionSourceReleasedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = false;
    }
}

Draw 設定為 true 時,筆刷會在具現化的 Unity LineRenderer 中產生點。While Draw is set to true, the brush will generate points in an instantiated Unity LineRenderer. 此預製專案的參考會保留在筆刷的 [ 筆觸預製專案 ] 欄位中。A reference to this prefab is kept in the brush's Stroke Prefab field.

private IEnumerator DrawOverTime()
{
    // Get the position of the tip
    Vector3 lastPointPosition = tip.position;

    ...

    // Create a new brush stroke
    GameObject newStroke = Instantiate(strokePrefab);
    LineRenderer line = newStroke.GetComponent<LineRenderer>();
    newStroke.transform.position = startPosition;
    line.SetPosition(0, tip.position);
    float initialWidth = line.widthMultiplier;

    // Generate points in an instantiated Unity LineRenderer
    while (draw)
    {
        // Move the last point to the draw point position
        line.SetPosition(line.positionCount - 1, tip.position);
        line.material.color = colorPicker.SelectedColor;
        brushRenderer.material.color = colorPicker.SelectedColor;
        lastPointAddedTime = Time.unscaledTime;
        // Adjust the width between 1x and 2x width based on strength of trigger pull
        line.widthMultiplier = Mathf.Lerp(initialWidth, initialWidth * 2, width);

        if (Vector3.Distance(lastPointPosition, tip.position) > minPositionDelta || Time.unscaledTime > lastPointAddedTime + maxTimeDelta)
        {
            // Spawn a new point
            lastPointAddedTime = Time.unscaledTime;
            lastPointPosition = tip.position;
            line.positionCount += 1;
            line.SetPosition(line.positionCount - 1, lastPointPosition);
        }
        yield return null;
    }
}

若要從色彩選擇器滾輪 UI 使用目前選取的色彩, BrushController 需要有 ColorPickerWheel 物件的參考。To use the currently selected color from the color picker wheel UI, BrushController needs to have a reference to the ColorPickerWheel object. 因為 BrushController 預製專案在執行時間具現化為取代控制器,所以在執行時間必須設定任何對場景中物件的參考。Because the BrushController prefab is instantiated at runtime as a replacement controller, any references to objects in the scene will have to be set at runtime. 在此情況下,我們會使用 GameObject FindObjectOfType 來找出 ColorPickerWheelIn this case we use GameObject.FindObjectOfType to locate the ColorPickerWheel:

private void OnEnable()
{
    // Locate the ColorPickerWheel
    colorPicker = FindObjectOfType<ColorPickerWheel>();

    // Assign currently selected color to the brush’s material color
    brushRenderer.material.color = colorPicker.SelectedColor;
    ...
}
  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button. 您將可以使用右邊控制器上的 [選取] 按鈕來繪製線條和繪圖。You will be able to draw the lines and paint using the select button on the right-hand controller.

第6章-使用 Select 輸入的物件產生Chapter 6 - Object spawning with Select input

目標Objectives

  • 瞭解如何使用 Select 和抓住按鈕輸入事件Learn how to use Select and Grasp button input events
  • 瞭解如何將物件具現化Learn how to instantiate objects

指示Instructions

  • 在 [ 專案 ] 面板的 [搜尋] 方塊中,輸入 ObjectSpawnerIn the Project panel, type ObjectSpawner in the search box. 您也可以在資產/AppPrefabs/上找到它You can also find it under Assets/AppPrefabs/

  • ObjectSpawner 預製專案拖曳到 [階層 ] 面板中Drag the ObjectSpawner prefab into the Hierarchy panel.

  • 按一下 [階層] 面板中的 [ ObjectSpawner ]。Click ObjectSpawner in the Hierarchy panel.

  • ObjectSpawner 有一個名為 Color Source 的欄位。ObjectSpawner has a field named Color Source.

  • 從 [階層 ] 面板中 ,將 [ ColorPickerWheel ] 參考拖曳到此欄位中。From the Hierarchy panel, drag the ColorPickerWheel reference into this field.

    物件 Spawner 偵測器

  • 按一下 [階層 ] 面板中的 [ ObjectSpawner ] 預製專案。Click the ObjectSpawner prefab in the Hierarchy panel.

  • 在 [偵測 ] 面板中,按兩下 [ ObjectSpawner 腳本] 以查看 Visual Studio 中的程式碼。In the Inspector panel, double click ObjectSpawner Script to see the code in Visual Studio.

ObjectSpawner 腳本ObjectSpawner script

ObjectSpawner 會將基本網格 (cube、球體、圓柱) 的複本具現化到空間中。The ObjectSpawner instantiates copies of a primitive mesh (cube, sphere, cylinder) into the space. 偵測到 InteractionSourcePressed 時,它會檢查 handedness,如果是 InteractionSourcePressType請選取 [事件]。When a InteractionSourcePressed is detected it checks the handedness and if it's an InteractionSourcePressType.Grasp or InteractionSourcePressType.Select event.

針對 理解 事件,它會將目前網格類型的索引遞增 (球體、cube、圓柱) For a Grasp event, it increments the index of current mesh type (sphere, cube, cylinder)

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    // Check handedness, see if it is left controller
    if (obj.state.source.handedness == handedness)
    {
        switch (obj.pressType)
        {
            // If it is Select button event, spawn object
            case InteractionSourcePressType.Select:
                if (state == StateEnum.Idle)
                {
                    // We've pressed the grasp - enter spawning state
                    state = StateEnum.Spawning;
                    SpawnObject();
                }
                break;

            // If it is Grasp button event
            case InteractionSourcePressType.Grasp:

                // Increment the index of current mesh type (sphere, cube, cylinder)
                meshIndex++;
                if (meshIndex >= NumAvailableMeshes)
                {
                    meshIndex = 0;
                }
                break;

            default:
                break;
        }
    }
}

針對 Select 事件,在 SpawnObject ( # B1 中,會具現化新的物件,並將其具現化,並釋出到全世界。For a Select event, in SpawnObject(), a new object is instantiated, un-parented and released into the world.

private void SpawnObject()
{
    // Instantiate the spawned object
    GameObject newObject = Instantiate(displayObject.gameObject, spawnParent);
    // Detach the newly spawned object
    newObject.transform.parent = null;
    // Reset the scale transform to 1
    scaleParent.localScale = Vector3.one;
    // Set its material color so its material gets instantiated
    newObject.GetComponent<Renderer>().material.color = colorSource.SelectedColor;
}

ObjectSpawner 會使用 ColorPickerWheel 來設定顯示物件材質的色彩。The ObjectSpawner uses the ColorPickerWheel to set the color of the display object's material. 產生的物件會被授與此材質的實例,以保留其色彩。Spawned objects are given an instance of this material so they will retain their color.

  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button.

您將可以使用 [理解] 按鈕來變更物件,並使用 [選取] 按鈕產生物件。You will be able to change the objects with the Grasp button and spawn objects with the Select button.

建立應用程式並部署到混合實境入口Build and deploy app to Mixed Reality Portal

  • 在 Unity 中,選取 [ File > Build Settings]。In Unity, select File > Build Settings.
  • 按一下 [ 新增開啟的場景 ],將目前的場景加入 組建中的場景Click Add Open Scenes to add current scene to the Scenes In Build.
  • 按一下 [建置]。Click Build.
  • 建立名為 "App" 的 新資料夾Create a New Folder named "App".
  • 按一下 應用程式 資料夾。Single click the App folder.
  • 按一下 [選擇資料夾]。Click Select Folder.
  • 當 Unity 完成時,將會出現檔案總管視窗。When Unity is done, a File Explorer window will appear.
  • 開啟 應用程式 資料夾。Open the App folder.
  • 按兩下 [ YourSceneName ] Visual Studio 方案檔。Double click YourSceneName.sln Visual Studio Solution file.
  • 使用 Visual Studio 中的頂端工具列,將目標從 Debug 變更為 Release ,以及從 ARM 變更為 X64Using the top toolbar in Visual Studio, change the target from Debug to Release and from ARM to X64.
  • 按一下 [裝置] 按鈕旁邊的下拉箭號,然後選取 [ 本機電腦]。Click on the drop-down arrow next to the Device button, and select Local Machine.
  • 按一下 [ Debug-> 啟動但不 在功能表中進行調試],或按 Ctrl + F5Click Debug -> Start Without debugging in the menu or press Ctrl + F5.

現在,應用程式已建立並安裝在混合實境入口中。Now the app is built and installed in Mixed Reality Portal. 您可以透過混合實境入口中的 [開始] 功能表再次啟動它。You can launch it again through Start menu in Mixed Reality Portal.

先進的設計-具有放射狀配置的筆刷工具Advanced design - Brush tools with radial layout

MixedReality213 Main

在本章中,您將瞭解如何使用自訂筆刷工具集合來取代預設的動作控制器模型。In this chapter, you will learn how to replace the default motion controller model with a custom brush tool collection. 針對您的參考,您可以在 [場景] 資料夾下找到完成的場景 MixedReality213AdvancedFor your reference, you can find the completed scene MixedReality213Advanced under Scenes folder.

指示Instructions

  • 在 [ 專案 ] 面板的 [搜尋] 方塊中,輸入 BrushSelectorIn the Project panel, type BrushSelector in the search box . 您也可以在資產/AppPrefabs/上找到它You can also find it under Assets/AppPrefabs/

  • BrushSelector 預製專案拖曳到 [階層 ] 面板中Drag the BrushSelector prefab into the Hierarchy panel.

  • 針對組織,建立稱為 筆刷 的空白 GameObjectFor organization, create an empty GameObject called Brushes

  • 將下列 prefabs 從 [ 專案 ] 面板拖曳至 筆刷Drag following prefabs from the Project panel into Brushes

    • 資產/AppPrefabs/BrushFatAssets/AppPrefabs/BrushFat
    • 資產/AppPrefabs/BrushThinAssets/AppPrefabs/BrushThin
    • 資產/AppPrefabs/橡皮擦Assets/AppPrefabs/Eraser
    • 資產/AppPrefabs/MarkerFatAssets/AppPrefabs/MarkerFat
    • 資產/AppPrefabs/MarkerThinAssets/AppPrefabs/MarkerThin
    • 資產/AppPrefabs/鉛筆Assets/AppPrefabs/Pencil

    筆刷

  • 按一下 [階層] 面板中的 [ MotionControllers 預製專案]。Click MotionControllers prefab in the Hierarchy panel.

  • 在 [偵測 ] 面板中,取消核取 [移動控制器] 視覺化檢視 上的 [永遠使用替代模型]In the Inspector panel, uncheck Always Use Alternate Right Model on the Motion Controller Visualizer

  • 在 [階層] 面板中,按一下 [ BrushSelector ]In the Hierarchy panel, click BrushSelector

  • BrushSelector 有一個名為 ColorPicker 的欄位BrushSelector has a field named ColorPicker

  • 從 [階層] 面板中,將 [ ColorPickerWheel ] 拖曳至 [偵測 ] 面板中 的 [ ColorPicker ] 欄位。From the Hierarchy panel, drag the ColorPickerWheel into ColorPicker field in the Inspector panel.

    將 ColorPickerWheel 指派給筆刷選取器

  • 在 [ 階層 ] 面板中,選取 [ BrushSelector 預製專案] 底下的 功能表 物件。In the Hierarchy panel, under BrushSelector prefab, select the Menu object.

  • 在 [偵測 ] 面板的 [ LineObjectCollection ] 元件底下,開啟 [ 物件 陣列] 下拉式清單。In the Inspector panel, under the LineObjectCollection component, open the Objects array dropdown. 您會看到6個空的插槽。You will see 6 empty slots.

  • 從 [階層 ] 面板中 ,將 [ 筆刷 ] GameObject 下的每個 prefabs 以任何順序拖曳至這些位置。From the Hierarchy panel, drag each of the prefabs parented under the Brushes GameObject into these slots in any order. (確定您是從場景拖曳 prefabs,而不是從專案資料夾中的 prefabs。 ) (Make sure you're dragging the prefabs from the scene, not the prefabs in the project folder.)

筆刷選取器

BrushSelector 預製專案BrushSelector prefab

因為 BrushSelector 會繼承 AttachToController,所以它會在 [偵測 ] 面板中顯示 Handedness元素 選項。Since the BrushSelector inherits AttachToController, it shows Handedness and Element options in the Inspector panel. 我們選取了 [ ],並 指向 [順向],將筆刷工具附加至右邊控制器。We selected Right and Pointing Pose to attach brush tools to the right hand controller with forward direction.

BrushSelector 會使用兩個公用程式:The BrushSelector makes use of two utilities:

  • 橢圓形:用來沿著橢圓形圖形來產生空間中的點。Ellipse: used to generate points in space along an ellipse shape.
  • LineObjectCollection:使用任何線條類別產生的點來散發物件 (例如橢圓形) 。LineObjectCollection: distributes objects using the points generated by any Line class (eg, Ellipse). 這是我們將用來沿著橢圓形圖形來放置筆刷的內容。This is what we'll be using to place our brushes along the Ellipse shape.

結合之後,這些公用程式可以用來建立放射狀功能表。When combined, these utilities can be used to create a radial menu.

LineObjectCollection 腳本LineObjectCollection script

LineObjectCollection 具有控制項的大小、位置和旋轉,以及沿著線條分佈的物件。LineObjectCollection has controls for the size, position and rotation of objects distributed along its line. 這對於建立星形功能表(例如筆刷選取器)很有用。This is useful for creating radial menus like the brush selector. 若要建立筆刷的外觀,而不會在接近中心選取的位置時相應增加,則 ObjectScale 曲線會尖峰于中間,並在邊緣 tapers。To create the appearance of brushes that scale up from nothing as they approach the center selected position, the ObjectScale curve peaks in the center and tapers off at the edges.

BrushSelector 腳本BrushSelector script

BrushSelector 的案例中,我們選擇使用程式動畫。In the case of the BrushSelector, we've chosen to use procedural animation. 首先, LineObjectCollection 腳本會將筆刷模型散發在橢圓形中。First, brush models are distributed in an ellipse by the LineObjectCollection script. 然後,每個筆刷都會根據選取專案,負責 維護其在 使用者手中的位置(視選取專案而定)。Then, each brush is responsible for maintaining its position in the user's hand based on its DisplayMode value, which changes based on the selection. 我們選擇了程式性方法,因為當使用者選取筆刷時,筆刷位置轉換會中斷的機率很高。We chose a procedural approach because of the high probability of brush position transitions being interrupted as the user selects brushes. Mecanim 動畫可以正常地處理中斷情形,但通常比簡單的 Lerp 作業更複雜。Mecanim animations can handle interruptions gracefully, but it tends to be more complicated than a simple Lerp operation.

BrushSelector 會使用這兩者的組合。BrushSelector uses a combination of both. 當偵測到觸控板輸入時,筆刷選項會變成可見,並沿著放射狀功能表向上擴充。When touchpad input is detected, brush options become visible and scale up along the radial menu. 在超時期間 (,表示使用者已進行選取) 筆刷選項調整大小,只留下選取的筆刷。After a timeout period (which indicates that the user has made a selection) the brush options scale down again, leaving only the selected brush.

視覺化觸控板輸入Visualizing touchpad input

即使已完全取代控制器模型,在原始模型輸入上顯示輸入可能會很有説明。Even in cases where the controller model has been completely replaced, it can be helpful to show input on the original model inputs. 這有助於實現使用者的動作。This helps to ground the user's actions in reality. 針對 BrushSelector ,我們選擇讓觸控板在收到輸入時短暫顯示。For the BrushSelector we've chosen to make the touchpad briefly visible when the input is received. 這是藉由從控制器中取出觸控板元素、將其材質取代為自訂材質來完成,然後根據收到的前次觸控板輸入將漸層套用至該材質的色彩。This was done by retrieving the Touchpad element from the controller, replacing its material with a custom material, then applying a gradient to that material's color based on the last time touchpad input was received.

protected override void OnAttachToController()
{
    // Turn off the default controller's renderers
    controller.SetRenderersVisible(false);

    // Get the touchpad and assign our custom material to it
    Transform touchpad;
    if (controller.TryGetElement(MotionControllerInfo.ControllerElementEnum.Touchpad, out touchpad))
    {
        touchpadRenderer = touchpad.GetComponentInChildren<MeshRenderer>();
        originalTouchpadMaterial = touchpadRenderer.material;
        touchpadRenderer.material = touchpadMaterial;
        touchpadRenderer.enabled = true;
    }

    // Subscribe to input now that we're parented under the controller
    InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
}

private void Update()
{
    ...
    // Update our touchpad material
    Color glowColor = touchpadColor.Evaluate((Time.unscaledTime - touchpadTouchTime) / touchpadGlowLossTime);
    touchpadMaterial.SetColor("_EmissionColor", glowColor);
    touchpadMaterial.SetColor("_Color", glowColor);
    ...
}

使用觸控板輸入的筆刷工具選項Brush tool selection with touchpad input

當筆刷選取器偵測到觸控板的已按下輸入時,它會檢查輸入的位置,以判斷其是否為左方或右方。When the brush selector detects touchpad's pressed input, it checks the position of the input to determine if it was to the left or right.

使用 selectPressedAmount 的筆觸粗細Stroke thickness with selectPressedAmount

而不是 InteractionSourcePressType。請選取 InteractionSourcePressed ( # B1 中的事件,您可以透過 selectPressedAmount 取得按下數量的類比值。Instead of the InteractionSourcePressType.Select event in the InteractionSourcePressed(), you can get the analog value of the pressed amount through selectPressedAmount. 您可以在 InteractionSourceUpdated ( # B1 中取出此值。This value can be retrieved in InteractionSourceUpdated().

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness)
    {
        if (obj.state.touchpadPressed)
        {
            // Check which side we clicked
            if (obj.state.touchpadPosition.x < 0)
            {
                currentAction = SwipeEnum.Left;
            }
            else
            {
                currentAction = SwipeEnum.Right;
            }

            // Ping the touchpad material so it gets bright
            touchpadTouchTime = Time.unscaledTime;
        }

        if (activeBrush != null)
        {
            // If the pressed amount is greater than our threshold, draw
            if (obj.state.selectPressedAmount >= selectPressedDrawThreshold)
            {
                activeBrush.Draw = true;
                activeBrush.Width = ProcessSelectPressedAmount(obj.state.selectPressedAmount);
            }
            else
            {
                // Otherwise, stop drawing
                activeBrush.Draw = false;
                selectPressedSmooth = 0f;
            }
        }
    }
}

橡皮擦腳本Eraser script

橡皮擦 是一種特殊類型的筆刷,會覆寫基底 筆刷DrawOverTime ( # B1 函數。Eraser is a special type of brush that overrides the base Brush's DrawOverTime() function. 當 Draw 為 true 時,橡皮擦會檢查其提示是否與任何現有的筆刷筆劃相交。While Draw is true, the eraser checks to see if its tip intersects with any existing brush strokes. 如果有,則會將它們加入至要壓縮和刪除的佇列。If it does, they are added to a queue to be shrunk down and deleted.

Advanced design-遙傳和 locomotionAdvanced design - Teleportation and locomotion

如果您想要允許使用者透過遙傳使用操縱杆來移動場景,請使用 MixedRealityCameraParent 而不是 MixedRealityCameraIf you want to allow the user to move around the scene with teleportation using thumbstick, use MixedRealityCameraParent instead of MixedRealityCamera. 您也需要新增 InputManagerDefaultCursorYou also need to add InputManager and DefaultCursor. 因為 MixedRealityCameraParent 已經將 MotionControllers界限 包含為子元件,所以您應該移除現有的 MotionControllers環境 預製專案。Since MixedRealityCameraParent already includes MotionControllers and Boundary as child components, you should remove existing MotionControllers and Environment prefab.

指示Instructions

  • 在 [階層] 面板中,刪除 [ MixedRealityCamera]、[環境] 和 [ MotionControllers ]In the Hierarchy panel, delete MixedRealityCamera, Environment and MotionControllers

  • 在 [ 專案] 面板 中,搜尋下列 prefabs,並將 其拖曳 到 [階層] 面板中:From the Project panel, search and drag the following prefabs into the Hierarchy panel:

    • 資產/AppPrefabs/Input/Prefabs/MixedRealityCameraParentAssets/AppPrefabs/Input/Prefabs/MixedRealityCameraParent
    • 資產/AppPrefabs/Input/Prefabs/InputManagerAssets/AppPrefabs/Input/Prefabs/InputManager
    • 資產/AppPrefabs/Input/Prefabs/Cursor/DefaultCursorAssets/AppPrefabs/Input/Prefabs/Cursor/DefaultCursor

    混合實境相機父系

  • 在 [階層] 面板中,按一下 [輸入管理員]In the Hierarchy panel, click Input Manager

  • 在 [偵測 ] 面板中,向下滾動至 簡單的單一指標選取器 區段In the Inspector panel, scroll down to the Simple Single Pointer Selector section

  • 從 [ 階層 ] 面板中,將 [ DefaultCursor ] 拖曳至 [ 游標 ] 欄位From the Hierarchy panel, drag DefaultCursor into Cursor field

    指派 DefaultCursor

  • 儲存 場景,然後按一下 [ 播放 ] 按鈕。Save the scene and click the play button. 您將能夠使用操縱杆來旋轉左右或傳送。You will be able to use the thumbstick to rotate left/right or teleport.

結束The end

這就是本教學課程的結尾!And that's the end of this tutorial! 您已了解︰You learned:

  • 如何在 Unity 的遊戲模式和執行時間中使用移動控制器模型。How to work with motion controller models in Unity's game mode and runtime.
  • 如何使用不同類型的按鈕事件和其應用程式。How to use different types of button events and their applications.
  • 如何覆迭控制器頂端的 UI 元素或完全自訂。How to overlay UI elements on top of the controller or fully customize it.

您現在已準備好開始使用移動控制器來建立您自己的沉浸式體驗!You are now ready to start creating your own immersive experience with motion controllers!

完成的場景Completed scenes

  • 在 Unity 的 [ 專案 ] 面板中,按一下 [ 場景 ] 資料夾。In Unity's Project panel click on the Scenes folder.
  • 您會發現兩個 Unity 場景 MixedReality213MixedReality213AdvancedYou will find two Unity scenes MixedReality213 and MixedReality213Advanced.
    • MixedReality213:已完成場景與單一筆刷MixedReality213: Completed scene with single brush
    • MixedReality213Advanced:已完成場景,具有具有 select 按鈕的按量範例的多筆刷MixedReality213Advanced: Completed scene with multiple brush with select button's press amount example

另請參閱See also