Unity MRTK Hololens2眼动交互

csharp 复制代码
/*
 * ==================================================================================================================
 *
 * UnityVersion : 2021.3.6f1
 * Description : 眼部交互基类
 * Author: 
 * CreateTime : 2023-10-11  09:43:20
 * Version : V1.0.0
 * 
 * ==================================================================================================================
 */

using System.Collections.Generic;
using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

namespace MRTKExtend.EyeTracking
{
    [RequireComponent(typeof(Collider))]
    public abstract class BaseFocus : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityFocusChangedHandler
    {
        [SerializeField] [Tooltip("是否启用焦点?")] private bool focusEnabled = true;

        /// <summary>
        /// 是否为启用了焦点
        /// </summary>
        public virtual bool FocusEnabled
        {
            get => focusEnabled;
            set => focusEnabled = value;
        }

        /// <summary>
        /// 此对象当前是否有焦点
        /// </summary>
        public virtual bool HasFocus => FocusEnabled && Focusers.Count > 0;

        /// <summary>
        /// 当前聚焦此对象的列表
        /// </summary>
        public List<IMixedRealityPointer> Focusers { get; } = new(0);

        /// <summary>
        /// 焦点进入
        /// </summary>
        public virtual void OnFocusEnter(FocusEventData eventData)
        {
        }

        /// <summary>
        /// 焦点退出
        /// </summary>
        public virtual void OnFocusExit(FocusEventData eventData)
        {
        }

        public virtual void OnBeforeFocusChange(FocusEventData eventData)
        {
            //如果是新的目标对象,将指针添加到焦点列表。
            if (eventData.NewFocusedObject == gameObject)
            {
                eventData.Pointer.FocusTarget = this;
                Focusers.Add(eventData.Pointer);
            }
            //如果是旧的聚焦目标对象,从列表中删除指针。

            else if (eventData.OldFocusedObject == gameObject)
            {
                Focusers.Remove(eventData.Pointer);

                //如果没有新的焦点目标,从指针中清除焦点目标。

                if (eventData.NewFocusedObject == null)
                {
                    eventData.Pointer.FocusTarget = null;
                }
            }
        }

        public virtual void OnFocusChanged(FocusEventData eventData)
        {
        }
    }
}
csharp 复制代码
/*
 * ==================================================================================================================
 *
 * UnityVersion : 2021.3.6f1
 * Description : 眼部交互
 * Author: 
 * CreateTime : 2023-10-11  09:21:40
 * Version : V1.0.0
 * 
 * ==================================================================================================================
 */

using System;
using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

namespace MRTKExtend.EyeTracking
{
    public abstract class BaseEyeFocus : BaseFocus
    {
        [Tooltip("可配置的持续时间,用于在用户查注释目标的时间超过此持续时间时触发事件。")] [SerializeField] [Range(0, 20)]
        private float timeToTriggerDwellInSec = 5;

        /// <summary>
        /// 停留时间
        /// </summary>
        private DateTime _dwellTimer;

        /// <summary>
        /// 是否持续注视
        /// </summary>
        private bool _isDwelling = false;

        /// <summary>
        /// 是否注视
        /// </summary>
        private bool _hadFocus = false;

        /// <summary>
        /// 处理光标进入目标时的突出显示目标。
        /// </summary>
        protected virtual void Update()
        {
            if (!HasFocus && _hadFocus)
            {
                OnEyeFocusStop();
                _isDwelling = false;
                _hadFocus = false;
            }
            else if (HasFocus)
            {
                if (!_hadFocus)
                {
                    OnEyeFocusStart();
                    _dwellTimer = DateTime.UtcNow;
                    _hadFocus = true;
                }
                else
                {
                    OnEyeFocusStay();

                    if (!_isDwelling && (DateTime.UtcNow - _dwellTimer).TotalSeconds > timeToTriggerDwellInSec)
                    {
                        OnEyeFocusDwell();
                        _isDwelling = true;
                    }
                }
            }
        }

        /// <inheritdoc />
        public override void OnBeforeFocusChange(FocusEventData eventData)
        {
            //如果注视新的目标对象,将指针添加到焦点列表。
            if (eventData.NewFocusedObject == gameObject &&
                eventData.Pointer.InputSourceParent.SourceType == InputSourceType.Eyes)
            {
                eventData.Pointer.FocusTarget = this;
                Focusers.Add(eventData.Pointer);
            }
            //如果注视是旧的聚焦目标对象,从列表中删除指针。
            else if (eventData.OldFocusedObject == gameObject)
            {
                Focusers.Remove(eventData.Pointer);

                // 如果没有新目标,从指针中清除焦点目标
                if (eventData.NewFocusedObject == null)
                {
                    eventData.Pointer.FocusTarget = null;
                }
            }
        }

        /// <summary>
        ///一旦眼睛凝视射线开始与该目标的碰撞体接触,就会触发。
        /// </summary>
        protected virtual void OnEyeFocusStart()
        {
        }

        /// <summary>
        /// 在眼睛凝视射线与该目标的碰撞体持续接触时触发。
        /// </summary>
        protected virtual void OnEyeFocusStay()
        {
        }

        /// <summary>
        ///一旦眼睛凝视射线停止与该目标的碰撞体,就会触发。
        /// </summary>
        protected virtual void OnEyeFocusStop()
        {
        }

        /// <summary>
        /// 一旦眼睛凝视射线与该目标的碰撞体接触指定时间后触发。
        /// </summary>
        protected virtual void OnEyeFocusDwell()
        {
        }
    }
}
csharp 复制代码
/*
 * ==================================================================================================================
 *
 * UnityVersion : 2021.3.6f1
 * Description : 功能描述
 * Author: 
 * CreateTime : 2023-10-10  16:09:27
 * Version : V1.0.0
 * 
 * ==================================================================================================================
 */

using MRTKExtend.EyeTracking;
using UnityEngine;

public class EyeTrackingTest : BaseEyeFocus
{
    protected override void OnEyeFocusStay()
    {
        Debug.Log("OnEyeFocusStay");
        //todo something
        RotateHitTarget();
    }

    protected override void OnEyeFocusStart()
    {
        Debug.Log("OnEyeFocusStart");
        //todo something

    }

    protected override void OnEyeFocusStop()
    {
        Debug.Log("OnEyeFocusStop");
        //todo something

    }

    protected override void OnEyeFocusDwell()
    {
        Debug.Log("OnEyeFocusDwell");
        //todo something

    }
    
    private void RotateHitTarget()
    {
        transform.localEulerAngles += new Vector3(0, 0.1f, 0);
    }
}

在场景中新建一个物体,将EyeTrackingTest组件挂载到新建的物体上就可以了

相关推荐
咔咔一顿操作12 分钟前
【CSS 3D 交互】打造沉浸式 3D 照片墙:结合 JS 实现拖拽交互
前端·javascript·css·3d·交互·css3
伽蓝_游戏4 小时前
UGUI源码剖析(15):Slider的运行时逻辑与编辑器实现
游戏·ui·unity·性能优化·c#·游戏引擎·.net
lrh302511 小时前
Custom SRP - Complex Maps
unity·srp·render pipeline
m0_4972141514 小时前
unity中通过拖拽,自定义scroll view中子物体顺序
unity·游戏引擎
地狱为王18 小时前
在Unity中实现DTLN-AEC处理音频文件的功能
unity·aec·降噪
360智汇云1 天前
k8s交互桥梁:走进Client-Go
golang·kubernetes·交互
SmalBox1 天前
【URP】Shader绘制棋盘格对比内置管线
unity·渲染
郝学胜-神的一滴2 天前
基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
c++·qt·线性代数·矩阵·游戏引擎·图形渲染
爬山算法2 天前
Redis(50) Redis哨兵如何与客户端进行交互?
数据库·redis·交互
EQ-雪梨蛋花汤2 天前
【Unity笔记】Unity 编辑器扩展:打造一个可切换 Config.assets 的顶部菜单插件
unity·编辑器·游戏引擎