眼球追踪技术 Unity+ HTC vive Pro + DroolonF1 (二)_unity

1.新建Camera

2.ViveSR--Prefabs中拖入预制体SRanipal Eye Framework,默认设置即可

3.ViveSR--Prefabs中拖入预制体 Gaze Ray Sample,调整Length Of Ray的数值,取决于你相机到物体之间的距离

4.新建Canvas,Render Mode改为 World Space,指定相机

5.在画布上添加几个Button,在按钮上添加Box Collider、 Rigidbody组件,取消重力

6.新建Layer,将Button设置为新建的Layer

7.自己写个触发事件或者Debug测试

8.运行unity ,校准视角,注视button查看效果。


PS:事件触发利用的是Ray射线,这一部分很简单,自行了解相关知识即可。

相关代码已经在我上传的DEMO里有写,非常详细,还有我汉化的备注。就不一一贴出来了。

//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
using System;
using System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

namespace ViveSR.anipal.Eye
{
public class SRanipal_EyeFocusSample : MonoBehaviour
{
public UnityEvent ThereEvent;
public GameObject CanvasTime;

public static FocusInfo FocusInfo;//焦点信息
private readonly float MaxDistance = 100;//最大距离
private readonly GazeIndex[] GazePriority = new GazeIndex[] { GazeIndex.COMBINE, GazeIndex.LEFT, GazeIndex.RIGHT };//注视 编号 1.结合2.左眼 3.右眼
private static EyeData eyeData = new EyeData();//眼部 数据
private bool eye_callback_registered = false;//眼睛回调函数是否被注销

private void Start()
{
//如果没有启用anipal的Eye模块。报错停止
if (!SRanipal_Eye_Framework.Instance.EnableEye)
{
enabled = false;
return;
}


}


private void Update()
{
//检查是否启用anipal的Eye模块的状态是否处于工作状态或者支持状态
if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING &&
SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) return;


//使用回调获取数据 并且 回调事件没有被注销
if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == true && eye_callback_registered == false)
{
SRanipal_Eye.WrapperRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye.CallbackBasic)EyeCallback));
eye_callback_registered = true;
}

//注销事件
else if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == false && eye_callback_registered == true)
{
SRanipal_Eye.WrapperUnRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye.CallbackBasic)EyeCallback));
eye_callback_registered = false;
}

//调用眼部事件
foreach (GazeIndex index in GazePriority)
{
Ray GazeRay;//发射射线
//int dart_board_layer_id = LayerMask.NameToLayer("NoReflection");//获取眼部注视的物体层级序号

bool eye_focus;//眼部注册 bool

//请求回调事件(返回序号【结合 左 右】返回射线 集中点信息 )
if (eye_callback_registered)
//向所有触发器发射 射线
eye_focus = SRanipal_Eye.Focus(index, out GazeRay, out FocusInfo, 0, MaxDistance, eyeData);//左右眼、返回射线、射线信息、角度、距离、眼部信息(帧率等)
else
eye_focus = SRanipal_Eye.Focus(index, out GazeRay, out FocusInfo, 0, MaxDistance);

//启用眼部追踪开关
if (eye_focus)
{
if (FocusInfo.collider.gameObject.tag == "CanvasUI")
{
addTime += Time.deltaTime;

CanvasTime.SetActive(true);
CanvasTime.transform.position = FocusInfo.collider.gameObject.transform.position;
CanvasTime.GetComponent<Image>().fillAmount += Time.deltaTime / 3;

if (addTime >= 3f)
{
ThereEvent.Invoke();//执行事件

addTime = 0f;
CanvasTime.SetActive(false);
CanvasTime.GetComponent<Image>().fillAmount = 0;
}

}
else
{
addTime = 0f;
CanvasTime.SetActive(false);
CanvasTime.GetComponent<Image>().fillAmount = 0;
}

}
}
}

float addTime = 0f;//倒计时


private void Release()
{
if (eye_callback_registered == true)
{
SRanipal_Eye.WrapperUnRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye.CallbackBasic)EyeCallback));
eye_callback_registered = false;
}
}
private static void EyeCallback(ref EyeData eye_data)
{
eyeData = eye_data;
}

}
}