首页 > 代码库 > 微软Hololens学院教程-Hologram Gaze(凝视)

微软Hololens学院教程-Hologram Gaze(凝视)

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 CameraHierarchy 面板中.
  • 右击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.
  • 设置 SDKUniversal 10Build TypeD3D.
  • 勾选 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 对象.
  • 拖拽此对象 CursorHierarchy.
  • 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;
        }
    }
}
GazeManager

接下来你要编辑 CusorManager.cs 代码实现以下目标:

1 判断哪个光标状态应该被激活,
2 根据光标是否在全息图上来不断更新光标状态
3 始终将光标放在用户正在注视的位置。

CursorManager.cs
技术分享
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;
    }
}
CursorManager

接下来可以再次发布部署一次APP,看一下当光标移动到全息图上时光标的变化。

全息图的凝视反馈:

步骤:

  • Hierarchy 面板中, 选择 Managers 对象.
  • 在右侧 Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框中输入 Interactible Manager. 选择此结果.
  • Hierarchy 面板中, 选择AstroMan 对象.
  • 在右侧 Inspector 面板中, 点击 Add Component 按钮.
  • 在搜索框中输入 Interactible . 选择此结果.

接下来你需要编辑 InteractibleManager.csInteractible.cs 两个代码文件来实现以下功能 :

  1. InteractibleManager.cs 脚本中,获取凝视射线击中的点和保存碰撞对象 collided GameObject.
  2. 当凝视交点在你可以交互的全息对象上时发送 GazeEntered message
  3. 当凝视交点离开你可以交互的全息对象上时发送 GazeExited message
  4. 在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");
            }
        }
    }
}
InteractibleManager
技术分享
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.

    }
}
Interactible

接下来你可以再一次发布部署到Hololens上查看当凝视点击中全息图时,全息图的反馈状态。

章节3 定位技术

目标:更容易定位到全息对象,稳定且自然到头部移动

步骤:

  1. Hierarchy 面板中, 选择 Managers 对象.
  2. 在右侧 Inspector 面板中, 点击 Add Component 按钮.
  3. 在搜索框中输入 Gaze Stabilizer. 选择此结果. 

接下来需要更新GazeManager 脚本

  1. 用VS打开GazeManager脚本 .
  2. 粘贴以下代码到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;
        }
    }
}
GazeManager

章节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全息对象一直保持在我们视角的边缘,无论我们走到哪里,我们都可以一眼就看到它。

步骤:

  1. Hierarchy 面板中, 选择 Managers 对象.
  2. 在右侧 Inspector 面板中, 点击 Add Component 按钮.
  3. 在搜索框中输入  Gesture Manager. 选择此结果.

接下来将使用SimpleTagalong.cs 文件,它会做到:

  1. 确定 Tag-Along 对象是否在摄像机边界内.
  2. 如果不在视椎体内, 定位 Tag-Along 对象部分到摄像机到视椎体内.
  3. 否则, 定位 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");
    }
}
Interactible

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.
    }
}
InteractibleAction

发布部署到设备上查看

原文链接https://developer.microsoft.com/en-us/windows/holographic/holograms_210

如有翻译上的错误请指正。谢谢

微软Hololens学院教程-Hologram Gaze(凝视)