這是老版本的教程,為了不耽誤大家的時間,請直接看原文,本文僅供參考哦!原文鏈接:https://developer.microsoft.com/EN-US/WINDOWS/HOLOGRAPHIC/holograms_210
Hololens的使用如果類比到計算機的使用,在輸入操作方面,Hololens了解用戶的操作意圖的第一個步驟是凝視,用戶的凝視射線呈現在場景中的點為凝視點,就好像是電腦中的鼠標光標點,凝視是第一步,是人與hololens操作的開始。
涉及凝視相關的知識點如下:
1 當用戶看着一個全息圖時,光標點會有反饋表現—表明用戶看到了全息圖,當用戶凝視視線離開全息圖時,光標點也要有反饋-表明用戶沒有在看全息圖。
2 當用戶注視到全息圖時,給於用戶更多反饋,例如聲音,全息圖當變化等。
3 使用定位技術使得用戶可以選中更小的全息圖。
4 添加方向指示圖標指引用戶找到全息圖
5全息指示面板追隨用戶移動,一直保持在用戶可見視角之內。
前提條件:
1 一台已經安裝好開發工具的windows10 pc
2 一些C#編程能力
3 已經完成了教程 Holograms-101
4 一個開發者模式的Hololens 設備
項目文件:
下載該教程所需文件files
章節1-Unity 設置
步驟:
- 開啟 Unity.
- 選擇 New Project.
- 給項目命名為 ModelExplorer.
- 保存地址到你下載的項目文件下的 Gaze 文件夾下
- 選擇為 3D項目.
- 點擊 Create Project.
發布到Hololens設備前的一些Unity必要設置
- 到Unity中選擇 Edit > Project Settings > Player.
- 在右側的Inspector Panel 面板中, 選擇 Windows Store 圖標.
- 展開 Other Settings 組.
- 在 Rendering 部分, 勾選 Virtual Reality Supported 選框 以添加一個新的 Virtual Reality SDKs 列表.
- 驗證 Windows Holographic 是否在列表中. 如果不在,選擇 + 按鈕將 Windows Holographic添加進列表.
- 在主工具欄中選擇Edit > Project Settings > Quality.
- 依然是右側的Inspector面板,在 Windows Store 圖標下點擊Default 下拉箭頭.
- 選擇 Fastest for Windows Store Apps.
導入美術資源
- 右擊Project 面板下Assets 文件夾.
- 點擊 Import Package > Custom Package.
- 定位到你下載的項目文件,然后選擇 ModelExplorer.unitypackage.
- 點擊 Open.
- 在出現的小窗口中,選擇 Import button.
場景設置
- 刪除 Hierarchy面板中的 Main Camera.
- 在Project面板下,找到 HoloToolkit 文件夾, 打開 Utilities folder, 然后打開 Prefabs folder.
- 拖拽Prefabs文件夾下的 Main Camera到Hierarchy 面板中.
- 右擊Hierarchy中的Directional Light 然后選擇 Delete.
- 在Project面板下的 Holograms 文件夾下, 拖拽以下資源到 Hierarchy面板中:
- AstroMan
- Lights
- SpaceAudioSource
- SpaceBackground
- Fitbox
- 選擇Hierarchy 面板下的Fitbox
- 拖拽場景中的 AstroMan 到右側Fitbox的Inspector 面板中的Hologram Collection 屬性
發布項目
- 保存當前場景: File > Save Scene As.
- 點擊 New Folder 命名新文件夾為 Scenes.
- 將當前場景命名為 “ModelExplorer” 然后保存在剛新建的 Scenes 文件夾下.
- 返回Unity,選擇 File > Build Settings.
- 點擊 Add Open Scenes 添加ModelExplorer場景.
- 選擇 Windows Store然后點擊Switch Platform.
- 設置 SDK 為 Universal 10 , Build Type 為 D3D.
- 勾選 Unity C# Projects.
- 點擊 Build.
- 創建一個新的文件夾命名為 "App".
- 單擊App文件夾
- 選擇 Select Folder.
- 當Unity Build完成后, 一個新的文件窗口會出現.
- 打開其 App Folder.
- 打開 ModelExplorer Visual Studio Solution.
- 在 Visual Studio中, 右擊 Package.appxmanifest 文件選擇查看代碼 View Code
- 定位代碼中的 TargetDeviceFamily 然后將名稱改掉, Name="Windows.Universal" 變為Name="Windows.Holographic".
- 點擊保存 Package.appxmanifest.
- 在 Visual Studio頂部工具欄中, 將 Debug 改為 Release ,將 ARM 改為 x86.
- 點擊Device 按鈕的下拉箭頭, 然后選擇遠程設備 Remote Machine.
- 輸入你設備的IP地址, 然后將認證模式設為 Universal (Unencrypted Protocol). 點擊 Select. 如果你不知道你設備的IP地址, 打開你的設備,在 Settings > Network & Internet > Advanced Options中可以查看到.
- 在VS的頂部工具欄, 點擊 Debug -> Start Without debugging 或者 Ctrl + F5. 如果這是你第一次部署到你的設備, 你需要進行配對 pair it with Visual Studio.
- 部署完成后, 可以使用選擇手勢關閉Fixbox.
章節2 光標點與目標反饋
光標設計遵循以下原則:
1 光標要一直出現在視角中
2 光標不能太小也不能太大
3 光標不能遮擋內容
步驟:
- 在Hierarchy 面板的頂部點擊Create 按鈕.
- 選擇 Create Empty.
- 點擊新創建的 GameObject 然后將它名稱改為為 "Managers".
- 在 Hierarchy 面板下, 選擇 Managers 對象.
- 在 Inspector 面板下, 點擊 Add Component 按鈕.
- 在搜索框輸入 Gaze Manager. 選擇此結果.
- 在 Inspector 面板下, 選擇 RaycastLayerMask 下拉單 將勾選的 TransparentFX 去掉.
- 在project面板下,找到HoloToolkit\Input\Prefabs 文件夾, 找到 Cursor 對象.
- 拖拽此對象 Cursor 到 Hierarchy.
- 在 Hierarchy 面板下, 選擇Cursor 對象.
- 在 Inspector 面板下, 點擊Add Component 按鈕.
- 在搜索框輸入Cursor Manager. 選擇此結果.
- 展開Hierarchy 面板下的Cursor 對象.
- 拖拽 CursorOnHolograms 對象到右側Inspector 面板下的Cursor On Holograms 屬性中。
- 同理拖拽 CursorOffHolograms 對象到右側Inspector 面板下的 Cursor Off Holograms 屬性中。
接下來你需要編輯GazeManager.cs 代碼,實現以下幾點:
1 執行一個物理射線physics raycast,
2 存儲射線交叉點的位置和法線position and normal
3 如果射線沒有擊中任何對象,將位置與法線設為默認值
GazeManager.cs

using HoloToolkit; using UnityEngine; /// <summary> /// GazeManager determines the location of the user's gaze, hit position and normals. /// </summary> public class GazeManager : Singleton<GazeManager> { [Tooltip("Maximum gaze distance for calculating a hit.")] public float MaxGazeDistance = 5.0f; [Tooltip("Select the layers raycast should target.")] public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers; /// <summary> /// Physics.Raycast result is true if it hits a Hologram. /// </summary> public bool Hit { get; private set; } /// <summary> /// HitInfo property gives access /// to RaycastHit public members. /// </summary> public RaycastHit HitInfo { get; private set; } /// <summary> /// Position of the user's gaze. /// </summary> public Vector3 Position { get; private set; } /// <summary> /// RaycastHit Normal direction. /// </summary> public Vector3 Normal { get; private set; } private GazeStabilizer gazeStabilizer; private Vector3 gazeOrigin; private Vector3 gazeDirection; void Awake() { /* TODO: DEVELOPER CODING EXERCISE 3.a */ // 3.a: GetComponent GazeStabilizer and assign it to gazeStabilizer. } private void Update() { // 2.a: Assign Camera's main transform position to gazeOrigin. gazeOrigin = Camera.main.transform.position; // 2.a: Assign Camera's main transform forward to gazeDirection. gazeDirection = Camera.main.transform.forward; // 3.a: Using gazeStabilizer, call function UpdateHeadStability. // Pass in gazeOrigin and Camera's main transform rotation. // 3.a: Using gazeStabilizer, get the StableHeadPosition and // assign it to gazeOrigin. UpdateRaycast(); } /// <summary> /// Calculates the Raycast hit position and normal. /// </summary> private void UpdateRaycast() { /* TODO: DEVELOPER CODING EXERCISE 2.a */ // 2.a: Create a variable hitInfo of type RaycastHit. RaycastHit hitInfo; // 2.a: Perform a Unity Physics Raycast. // Collect return value in public property Hit. // Pass in origin as gazeOrigin and direction as gazeDirection. // Collect the information in hitInfo. // Pass in MaxGazeDistance and RaycastLayerMask. Hit = Physics.Raycast(gazeOrigin, gazeDirection, out hitInfo, MaxGazeDistance, RaycastLayerMask); // 2.a: Assign hitInfo variable to the HitInfo public property // so other classes can access it. HitInfo = hitInfo; if (Hit) { // If raycast hit a hologram... // 2.a: Assign property Position to be the hitInfo point. Position = hitInfo.point; // 2.a: Assign property Normal to be the hitInfo normal. Normal = hitInfo.normal; } else { // If raycast did not hit a hologram... // Save defaults ... // 2.a: Assign Position to be gazeOrigin plus MaxGazeDistance times gazeDirection. Position = gazeOrigin + (gazeDirection * MaxGazeDistance); // 2.a: Assign Normal to be the user's gazeDirection. Normal = gazeDirection; } } }
接下來你要編輯 CusorManager.cs 代碼實現以下目標:
1 判斷哪個光標狀態應該被激活,
2 根據光標是否在全息圖上來不斷更新光標狀態
3 始終將光標放在用戶正在注視的位置。

using HoloToolkit; using UnityEngine; /// <summary> /// CursorManager class takes Cursor GameObjects. /// One that is on Holograms and another off Holograms. /// Shows the appropriate Cursor when a Hologram is hit. /// Places the appropriate Cursor at the hit position. /// Matches the Cursor normal to the hit surface. /// </summary> public class CursorManager : Singleton<CursorManager> { [Tooltip("Drag the Cursor object to show when it hits a hologram.")] public GameObject CursorOnHolograms; [Tooltip("Drag the Cursor object to show when it does not hit a hologram.")] public GameObject CursorOffHolograms; void Awake() { if (CursorOnHolograms == null || CursorOffHolograms == null) { return; } // Hide the Cursors to begin with. CursorOnHolograms.SetActive(false); CursorOffHolograms.SetActive(false); } void Update() { /* TODO: DEVELOPER CODING EXERCISE 2.b */ if (GazeManager.Instance == null || CursorOnHolograms == null || CursorOffHolograms == null) { return; } if (GazeManager.Instance.Hit) { // 2.b: SetActive true the CursorOnHolograms to show cursor. CursorOnHolograms.SetActive(true); // 2.b: SetActive false the CursorOffHolograms hide cursor. CursorOffHolograms.SetActive(false); } else { // 2.b: SetActive true CursorOffHolograms to show cursor. CursorOffHolograms.SetActive(true); // 2.b: SetActive false CursorOnHolograms to hide cursor. CursorOnHolograms.SetActive(false); } // 2.b: Assign gameObject's transform position equals GazeManager's instance Position. gameObject.transform.position = GazeManager.Instance.Position; // 2.b: Assign gameObject's transform up vector equals GazeManager's instance Normal. gameObject.transform.up = GazeManager.Instance.Normal; } }
接下來可以再次發布部署一次APP,看一下當光標移動到全息圖上時光標的變化。
全息圖的凝視反饋:
步驟:
- 在 Hierarchy 面板中, 選擇 Managers 對象.
- 在右側 Inspector 面板中, 點擊 Add Component 按鈕.
- 在搜索框中輸入 Interactible Manager. 選擇此結果.
- 在 Hierarchy 面板中, 選擇AstroMan 對象.
- 在右側 Inspector 面板中, 點擊 Add Component 按鈕.
- 在搜索框中輸入 Interactible . 選擇此結果.
接下來你需要編輯 InteractibleManager.cs 和 Interactible.cs 兩個代碼文件來實現以下功能 :
- 在 InteractibleManager.cs 腳本中,獲取凝視射線擊中的點和保存碰撞對象 collided GameObject.
- 當凝視交點在你可以交互的全息對象上時發送 GazeEntered message
- 當凝視交點離開你可以交互的全息對象上時發送 GazeExited message
- 在Interactible.cs 代碼中處理GazeEntered和GazeExited回調。

using HoloToolkit; using UnityEngine; /// <summary> /// InteractibleManager keeps tracks of which GameObject /// is currently in focus. /// </summary> public class InteractibleManager : Singleton<InteractibleManager> { public GameObject FocusedGameObject { get; private set; } private GameObject oldFocusedGameObject = null; void Start() { FocusedGameObject = null; } void Update() { /* TODO: DEVELOPER CODING EXERCISE 2.c */ oldFocusedGameObject = FocusedGameObject; if (GazeManager.Instance.Hit) { RaycastHit hitInfo = GazeManager.Instance.HitInfo; if (hitInfo.collider != null) { // 2.c: Assign the hitInfo's collider gameObject to the FocusedGameObject. FocusedGameObject = hitInfo.collider.gameObject; } else { FocusedGameObject = null; } } else { FocusedGameObject = null; } if (FocusedGameObject != oldFocusedGameObject) { ResetFocusedInteractible(); if (FocusedGameObject != null) { if (FocusedGameObject.GetComponent<Interactible>() != null) { // 2.c: Send a GazeEntered message to the FocusedGameObject. FocusedGameObject.SendMessage("GazeEntered"); } } } } private void ResetFocusedInteractible() { if (oldFocusedGameObject != null) { if (oldFocusedGameObject.GetComponent<Interactible>() != null) { // 2.c: Send a GazeExited message to the oldFocusedGameObject. oldFocusedGameObject.SendMessage("GazeExited"); } } } }

using UnityEngine; /// <summary> /// The Interactible class flags a Game Object as being "Interactible". /// Determines what happens when an Interactible is being gazed at. /// </summary> public class Interactible : MonoBehaviour { [Tooltip("Audio clip to play when interacting with this hologram.")] public AudioClip TargetFeedbackSound; private AudioSource audioSource; private Material[] defaultMaterials; void Start() { defaultMaterials = GetComponent<Renderer>().materials; // Add a BoxCollider if the interactible does not contain one. Collider collider = GetComponentInChildren<Collider>(); if (collider == null) { gameObject.AddComponent<BoxCollider>(); } EnableAudioHapticFeedback(); } private void EnableAudioHapticFeedback() { // If this hologram has an audio clip, add an AudioSource with this clip. if (TargetFeedbackSound != null) { audioSource = GetComponent<AudioSource>(); if (audioSource == null) { audioSource = gameObject.AddComponent<AudioSource>(); } audioSource.clip = TargetFeedbackSound; audioSource.playOnAwake = false; audioSource.spatialBlend = 1; audioSource.dopplerLevel = 0; } } /* TODO: DEVELOPER CODING EXERCISE 2.d */ void GazeEntered() { for (int i = 0; i < defaultMaterials.Length; i++) { // 2.d: Uncomment the below line to highlight the material when gaze enters. defaultMaterials[i].SetFloat("_Highlight", .25f); } } void GazeExited() { for (int i = 0; i < defaultMaterials.Length; i++) { // 2.d: Uncomment the below line to remove highlight on material when gaze exits. defaultMaterials[i].SetFloat("_Highlight", 0f); } } void OnSelect() { for (int i = 0; i < defaultMaterials.Length; i++) { defaultMaterials[i].SetFloat("_Highlight", .5f); } // Play the audioSource feedback when we gaze and select a hologram. if (audioSource != null && !audioSource.isPlaying) { audioSource.Play(); } /* TODO: DEVELOPER CODING EXERCISE 6.a */ // 6.a: Handle the OnSelect by sending a PerformTagAlong message. } }
接下來你可以再一次發布部署到Hololens上查看當凝視點擊中全息圖時,全息圖的反饋狀態。
章節3 定位技術
目標:更容易定位到全息對象,穩定且自然到頭部移動
步驟:
- 在 Hierarchy 面板中, 選擇 Managers 對象.
- 在右側 Inspector 面板中, 點擊 Add Component 按鈕.
- 在搜索框中輸入 Gaze Stabilizer. 選擇此結果.
接下來需要更新GazeManager 腳本
- 用VS打開GazeManager腳本 .
- 粘貼以下代碼到GazeManager.cs

using HoloToolkit; using UnityEngine; /// <summary> /// GazeManager determines the location of the user's gaze, hit position and normals. /// </summary> public class GazeManager : Singleton<GazeManager> { [Tooltip("Maximum gaze distance for calculating a hit.")] public float MaxGazeDistance = 5.0f; [Tooltip("Select the layers raycast should target.")] public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers; /// <summary> /// Physics.Raycast result is true if it hits a Hologram. /// </summary> public bool Hit { get; private set; } /// <summary> /// HitInfo property gives access /// to RaycastHit public members. /// </summary> public RaycastHit HitInfo { get; private set; } /// <summary> /// Position of the user's gaze. /// </summary> public Vector3 Position { get; private set; } /// <summary> /// RaycastHit Normal direction. /// </summary> public Vector3 Normal { get; private set; } private GazeStabilizer gazeStabilizer; private Vector3 gazeOrigin; private Vector3 gazeDirection; void Awake() { /* TODO: DEVELOPER CODING EXERCISE 3.a */ // 3.a: GetComponent GazeStabilizer and assign it to gazeStabilizer. gazeStabilizer = GetComponent<GazeStabilizer>(); } private void Update() { // 2.a: Assign Camera's main transform position to gazeOrigin. gazeOrigin = Camera.main.transform.position; // 2.a: Assign Camera's main transform forward to gazeDirection. gazeDirection = Camera.main.transform.forward; // 3.a: Using gazeStabilizer, call function UpdateHeadStability. // Pass in gazeOrigin and Camera's main transform rotation. gazeStabilizer.UpdateHeadStability(gazeOrigin, Camera.main.transform.rotation); // 3.a: Using gazeStabilizer, get the StableHeadPosition and // assign it to gazeOrigin. gazeOrigin = gazeStabilizer.StableHeadPosition; UpdateRaycast(); } /// <summary> /// Calculates the Raycast hit position and normal. /// </summary> private void UpdateRaycast() { /* TODO: DEVELOPER CODING EXERCISE 2.a */ // 2.a: Create a variable hitInfo of type RaycastHit. RaycastHit hitInfo; // 2.a: Perform a Unity Physics Raycast. // Collect return value in public property Hit. // Pass in origin as gazeOrigin and direction as gazeDirection. // Collect the information in hitInfo. // Pass in MaxGazeDistance and RaycastLayerMask. Hit = Physics.Raycast(gazeOrigin, gazeDirection, out hitInfo, MaxGazeDistance, RaycastLayerMask); // 2.a: Assign hitInfo variable to the HitInfo public property // so other classes can access it. HitInfo = hitInfo; if (Hit) { // If raycast hit a hologram... // 2.a: Assign property Position to be the hitInfo point. Position = hitInfo.point; // 2.a: Assign property Normal to be the hitInfo normal. Normal = hitInfo.normal; } else { // If raycast did not hit a hologram... // Save defaults ... // 2.a: Assign Position to be gazeOrigin plus MaxGazeDistance times gazeDirection. Position = gazeOrigin + (gazeDirection * MaxGazeDistance); // 2.a: Assign Normal to be the user's gazeDirection. Normal = gazeDirection; } } }
章節4 方向指示器
給光標添加一個方向箭頭使得用戶更容易找到全息對象。
步驟:
- 點擊Hierarchy 面板下的AstroMan 對象然后點擊小箭頭展開它
- 選中AstroMan下的DirectionalIndicator.
- 在右側的 Inspector面板中點擊Add Component 按鈕.
- 在搜索框輸入Direction Indicator. 選擇此結果.
- 此時拖拽Hierarchy面板下的Cursor 對象 到右側Inspector面板下Cursor屬性中.
- 在 Project 面板下, 拖拽 Holograms 文件夾下的 DirectionalIndicator 資源到右側Inspector中的Directional Indicator 屬性里
- 部署發布項目
- 看方向指示器如何幫助你找到宇航員
章節5 廣告牌
我們使用一個廣告牌來使得全息對象始終面向用戶
- 在 Hierarchy 面板中, 選擇 AstroMan 對象.
- 在右側的 Inspector面板中點擊Add Component 按鈕.
- 在搜索框輸入Billboard. 選擇此結果.
- 在Inspector面板中 將Pivot Axis屬性設置為Y.
- 現在可以發布到Hololens上看看效果
- 看看全息圖是不是一直都面向你,無論你怎么轉換視角
在做接下來的教程時先把 AstroMan 中的Billboard 腳本刪掉
章節6 追隨標簽
使用追隨標簽可以使得我們的全息對象追隨我們到房間的任何位置。
追隨全息對象的設計應遵循以下原則:
1 全息內容應該在視角范圍內一眼就可以看到
2全息內容不能顯示在用戶前進路上
3 頭部鎖定內容是不舒服的
我們可以想象這個Tag-along全息對象一直保持在我們視角的邊緣,無論我們走到哪里,我們都可以一眼就看到它。
步驟:
- 在 Hierarchy 面板中, 選擇 Managers 對象.
- 在右側 Inspector 面板中, 點擊 Add Component 按鈕.
- 在搜索框中輸入 Gesture Manager. 選擇此結果.
接下來將使用SimpleTagalong.cs 文件,它會做到:
- 確定 Tag-Along 對象是否在攝像機邊界內.
- 如果不在視椎體內, 定位 Tag-Along 對象部分到攝像機到視椎體內.
- 否則, 定位 Tag-Along 對象到離用戶固定距離的位置上。
接下來要做:
- 在 Holograms 文件夾下找到 Tagalong asset並點擊.
- 在右側 Inspector面板中, 上方有個Tag 下拉列表,點擊 Add Tag ….
- 點擊+ ,然后將 Tag 0 命名為 TagAlong.
- 在 Holograms 文件夾下點擊 Tagalong asset然后點擊右側Inspector面板中的Tag dropdown.
- 選擇 TagAlong 標簽.
- 我們必須編輯 Interactible.cs 腳本 發送信息到 InteractibleAction.

using UnityEngine; /// <summary> /// The Interactible class flags a Game Object as being "Interactible". /// Determines what happens when an Interactible is being gazed at. /// </summary> public class Interactible : MonoBehaviour { [Tooltip("Audio clip to play when interacting with this hologram.")] public AudioClip TargetFeedbackSound; private AudioSource audioSource; private Material[] defaultMaterials; void Start() { defaultMaterials = GetComponent<Renderer>().materials; // Add a BoxCollider if the interactible does not contain one. Collider collider = GetComponentInChildren<Collider>(); if (collider == null) { gameObject.AddComponent<BoxCollider>(); } EnableAudioHapticFeedback(); } private void EnableAudioHapticFeedback() { // If this hologram has an audio clip, add an AudioSource with this clip. if (TargetFeedbackSound != null) { audioSource = GetComponent<AudioSource>(); if (audioSource == null) { audioSource = gameObject.AddComponent<AudioSource>(); } audioSource.clip = TargetFeedbackSound; audioSource.playOnAwake = false; audioSource.spatialBlend = 1; audioSource.dopplerLevel = 0; } } /* TODO: DEVELOPER CODING EXERCISE 2.d */ void GazeEntered() { for (int i = 0; i < defaultMaterials.Length; i++) { // 2.d: Uncomment the below line to highlight the material when gaze enters. defaultMaterials[i].SetFloat("_Highlight", .25f); } } void GazeExited() { for (int i = 0; i < defaultMaterials.Length; i++) { // 2.d: Uncomment the below line to remove highlight on material when gaze exits. defaultMaterials[i].SetFloat("_Highlight", 0f); } } void OnSelect() { for (int i = 0; i < defaultMaterials.Length; i++) { defaultMaterials[i].SetFloat("_Highlight", .5f); } // Play the audioSource feedback when we gaze and select a hologram. if (audioSource != null && !audioSource.isPlaying) { audioSource.Play(); } /* TODO: DEVELOPER CODING EXERCISE 6.a */ // 6.a: Handle the OnSelect by sending a PerformTagAlong message. SendMessage("PerformTagAlong"); } }
InteractibleAction.cs腳本在您注視全息圖時執行自定義操作。 讓我們更新它與標簽一起使用。
- Complete the coding exercise or change it to this:
- 在 Hierarchy 面板的頂部的搜索框內輸入ChestButton_Center 然后選擇它.
- 在右側Inspector 面板下點擊 Add Component 按鈕.
- 在搜索框內輸入 Interactible Action. 並選擇
- 在project面板下 Holograms 文件夾中找到 Tagalong asset.
- 選中Hierarchy面板下的 ChestButton_Center 對象. 拖拽 TagAlong 對象從 Project 面板到右側 Inspector 面板中到 Object to TagAlong property.
- Double click the InteractibleAction script to open it in Visual Studio.

using HoloToolkit; using UnityEngine; /// <summary> /// InteractibleAction performs custom actions when you gaze at the holograms. /// </summary> public class InteractibleAction : MonoBehaviour { [Tooltip("Drag the Tagalong prefab asset you want to display.")] public GameObject ObjectToTagAlong; void PerformTagAlong() { if (ObjectToTagAlong == null) { return; } // Recommend having only one tagalong. GameObject existingTagAlong = GameObject.FindGameObjectWithTag("TagAlong"); if (existingTagAlong != null) { return; } GameObject instantiatedObjectToTagAlong = GameObject.Instantiate(ObjectToTagAlong); instantiatedObjectToTagAlong.SetActive(true); /* TODO: DEVELOPER CODING EXERCISE 6.b */ // 6.b: AddComponent Billboard to instantiatedObjectToTagAlong. // So it's always facing the user as they move. instantiatedObjectToTagAlong.AddComponent<Billboard>(); // 6.b: AddComponent SimpleTagalong to instantiatedObjectToTagAlong. // So it's always following the user as they move. instantiatedObjectToTagAlong.AddComponent<SimpleTagalong>(); // 6.b: Set any public properties you wish to experiment with. } }
發布部署到設備上查看
原文鏈接https://developer.microsoft.com/en-us/windows/holographic/holograms_210
如有翻譯上的錯誤請指正。謝謝