如何使用眼动仪在UGUI中模拟按钮相关事件

最近在开发一款使用Tobii眼动仪控制的游戏,然后界面上的按钮都是使用UGUI,在前期用鼠标控制表现良好,但是最终需要用眼动仪控制按钮。而Unity默认的按钮是不支持眼动仪点击按钮的,并且Tobii眼动仪提供的API也只能拿到眼睛看到的坐标。

最后经过调查,发现Unity是通过StandaloneInputModule发送鼠标点击事件的,所以我利用已有的StandaloneInputModule源码重新写了一个GazeInputModle,最后实现了这个需求。目前眼动仪只要捕捉到眼光在按钮上停留两秒就会触发鼠标点击事件。

以下是主要的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using Tobii.Gaming;

public class GazeInputModule : 
{
    private GameObject currentOverGameObject;
    private PointerEventData pointerEventData;
    private float durationTime;

    protected void HandlePointerExitAndEnter2(PointerEventData currentPointerData, GameObject newEnterTarget)
    {
        // if we have no target / pointerEnter has been deleted 
        // just send exit events to anything we are tracking 
        // then exit 
        if (newEnterTarget == null || currentPointerData.pointerEnter == null)
        {
            for (var i = 0; i < currentPointerData.hovered.Count; ++i)
                ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler);
            currentPointerData.hovered.Clear();
            if (newEnterTarget == null)
            {
                currentPointerData.pointerEnter = newEnterTarget;
                return;
            }
        }
        // if we have not changed hover target 
        if (currentPointerData.pointerEnter == newEnterTarget && newEnterTarget)
            return;
        GameObject commonRoot = FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget);
        // and we already an entered object from last time 
        if (currentPointerData.pointerEnter != null)
        {
            // send exit handler call to all elements in the chain 
            // until we reach the new target, or null! 
            Transform t = currentPointerData.pointerEnter.transform;
            while (t != null)
            {
                // if we reach the common root break out! 
                if (commonRoot != null && commonRoot.transform == t)
                    break;
                ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler);
                currentPointerData.hovered.Remove(t.gameObject);
                t = t.parent;
            }
        }
        // now issue the enter call up to but not including the common root 
        currentPointerData.pointerEnter = newEnterTarget;
        if (newEnterTarget != null)
        {
            Transform t = newEnterTarget.transform;
            while (t != null && t.gameObject != commonRoot)
            {
                ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler);
                currentPointerData.hovered.Add(t.gameObject);
                t = t.parent;
            }
        }
    }

    public void ProcessPoint()
    {
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(pointerEventData, results);

        // Debug.Log("mousePosition=" + Input.mousePosition + ", count=" + results.Count);

        RaycastResult raycastResult = FindFirstRaycast(results);
        HandlePointerExitAndEnter2(pointerEventData, raycastResult.gameObject);

        if (raycastResult.gameObject == pointerEventData.pointerEnter && raycastResult.gameObject != null)
        {
            durationTime += Time.deltaTime;
        }
        else
        {
            durationTime = 0;
        }

        if (durationTime > Configuration.GetFloat("InputMode.GazeClickDurationTime", 2)) //看一个对象两秒触发点击事件,可以配置
        {
            Debug.Log("Send Click event, name=" + raycastResult.gameObject.name);
            ExecuteEvents.Execute(raycastResult.gameObject, pointerEventData, ExecuteEvents.pointerClickHandler);
            durationTime = 0;
        }
    }
    
    public void Update()
    {
        if (pointerEventData == null)
        {
            pointerEventData = new PointerEventData(gameObject.GetComponent<EventSystem>());
        }

        if (Configuration.GetBool("InputMode.TestMode", false) == false) //如果是测试模式则使用鼠标模拟眼动仪,便于测试
        {
            GazePoint gazePoint = TobiiAPI.GetGazePoint();
            if (gazePoint.IsValid)
            {
                pointerEventData.position = gazePoint.Screen;
                ProcessPoint();
            }
        }
        else
        {
            pointerEventData.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
            ProcessPoint();
        }
    }

    public override void Process()
    {
        //do nothing to avoid mouse event cover ours 
    }
    
    
}

  主要继承了StandaloneInputModule,然后在Update里检测点是否停留在按钮上。

  用的时候需要把这个脚本挂载在EventSystem对象上,同时需要disable对象上的StandaloneInputModule,否则在选中按钮时每个Module都会发送PointerEnter事件。

  目前只实现了PointerEnter、PointerExit、PointerClick事件,如果有需要可以增加其他事件。

  代码中Configuration相关方法是自己写一个配置类,用的时候需要修改下这些代码。

转载于:https://www.cnblogs.com/liu102401/p/10241435.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你好!要使用 Leap Motion 控制 Unity3D 模型,需要进行以下步骤: 1. 下载并安装 Leap Motion SDK,官方网站为:https://developer.leapmotion.com/sdk-leap-motion-controller/ 2. 在 Unity3D 创建一个新项目。 3. 在 Unity3D 导入 Leap Motion SDK。在 Unity3D 菜单栏选择 Assets -> Import Package -> Custom Package,选择下载好的 Leap Motion SDK,点击 Import。 4. 创建一个空的 GameObject,并将 LeapHandController.cs 组件添加到它上面。 5. 在 Unity3D 创建一个可移动的模型(例如一个球)。 6. 将 Leap Motion 手势与模型控制器相连接。例如,当手掌向上移动时,模型也向上移动。 7. 进行测试并调整模型控制器以实现更好的控制效果。 希望这些步骤能够帮助你完成 Leap Motion 控制 Unity3D 模型的任务! ### 回答2: Leap Motion是一种新型的手势识别设备,可以跟踪人类手部的运动。它可以让我们通过手势控制应用程序,游戏或模型等内容。在Unity3D,我们可以将Leap Motion集成到场景,以实现手势控制3D模型的效果。 首先,我们需要在Unity3D安装Leap Motion SDK插件并导入我们想要使用的模型。然后,我们需要创建一个新的场景,将插件放置到场景,并将其与Leap Motion设备连接。 随着Leap Motion设备的逐渐普及,越来越多的开发者开始使用它来实现手势控制3D模型。与传统的按键和鼠标控制方式相比,Leap Motion可提供更自然、更直观的交互方式。它可以识别多种手势,如手指移动、手指握拳、手势旋转、手掌张开等等。通过合理地利用Leap Motion设备,我们可以实现更高效的用户体验。 然而,在使用Leap Motion进行手势控制时也有一些挑战。例如,用户的手势可能存在较大的误差,需要进行预处理和处理以确保正确的交互响应。此外,用户可能存在手势识别的困难,需要进行适当的训练和指导。 在实际开发过程,我们可以通过官方提供的文档、示例和开发者社区进行学习和交流,以进一步了解如何使用Leap Motion控制Unity3D模型。无疑,Leap Motion可以为Unity3D开发者提供更多创新的机会,让我们拭目以待未来的发展。 ### 回答3: Leap Motion 是一款独具特色的人体工程学产品,能够通过传感器实现手部及手指的动作捕捉。而 Unity3D 是一款游戏引擎,能够让开发者创建出具有游戏性能力的应用程序,包括游戏和 VR 等领域。那么,如何将 Leap Motion 应用到 Unity3D ,实现手势控制游戏模型呢? 首先,需要引入 Leap Motion SDK,并导入 Leap Motion 的插件。然后,通过调用 Leap Motion 提供的 API,可以获得手部及手指的数据信息,进而应用到游戏场景。 其次,需要编写脚本,来实现手势控制游戏模型,例如移动、缩放、旋转等操作。比如,在控制旋转时,可以将手指的旋转角度映射到游戏物体的旋转角度。 在应用 Leap Motion 控制 Unity3D 模型时,需要注意以下几点: 1. 必须保证 Leap Motion 传感器能够捕捉到手势数据,并调整好传感器的摆放角度,以保证传感器能够准确地捕捉到手势数据。 2. 需要通过调整脚本的参数,来实现手势控制的精度和敏感度,以便让用户更加流畅地控制游戏模型。 3. 对于不同类型的游戏模型,需要编写不同的控制代码,以适应不同的游戏场景。 总之,Leap Motion 控制 Unity3D 模型的应用,可以给用户带来更加直观、丰富的游戏体验。随着技术的不断发展,我们可以期待 Leap Motion 与 Unity3D 之间更多的结合,带来更好的用户体验和应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值