Unity3D for VR 学习(5): VR Gaze Input

      在VR中,最“贴切”的输入方式是眼神,即 VR Gaze Input,如盯着某UGUI UI、某GameObject,2s后触发事件–  显示ToolTip或者切换场景等。 因为这不需要蓝牙手柄输入,显得更自然且方便,风靡VR Gear的Lamper VR游戏,就是Gaze Input(陀螺仪)的典范—可顺利完成游戏的全部过程,的确很酷。

image

 

UGUI UI Gaze 选择

1 GazeInputModule(继承自PointerInputModule),挂到EventSystem实现。

2 通过输入按钮触发选择事件;或者Gaze 2s,触发选择事件。

   这里使用了raycasting,故要求Canvas是Word坐标系,且要求有raphic Raycaster组件,并挂上Center Eye Camera(其他L、R VR Eye未测试)。

3 EventSystem上,disable StandaloneInputModule & TouchInputModule。

4 会触发IPointEnter事件,通过查看Button的源码知道会触发Button.Hightlight高亮

 

GameObject Gaze 选择

5 在上面UGUI的基础上,给Camera添加PhysicsRaycaster组件

6 给GameObject,如Cube添加相应EventTriger:通过添加EventTrigger组件或者一个继承IPointDown**的脚本,来响应对应的Event即可。

 

备注:在UGUI开源工程中,有很多源码值得解读

如:ExecuteEvents.cs,核心代码片段(IEventSystemHandler):

public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler
        {
            var internalHandlers = s_HandlerListPool.Get();
            GetEventList<T>(target, internalHandlers);
            //    if (s_InternalHandlers.Count > 0)
            //        Debug.Log("Executinng " + typeof (T) + " on " + target);

            for (var i = 0; i < internalHandlers.Count; i++)
            {
                T arg;
                try
                {
                    arg = (T)internalHandlers[i];
                }
                catch (Exception e)
                {
                    var temp = internalHandlers[i];
                    Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(T).Name, temp.GetType().Name), e));
                    continue;
                }

                try
                {
                    functor(arg, eventData);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }

            var handlerCount = internalHandlers.Count;
            s_HandlerListPool.Release(internalHandlers);
            return handlerCount > 0;
        }

 

如:PhysicsRaycaster.cs ,核心代码片段(Physics.RaycastAll):

public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
        {
            if (eventCamera == null)
                return;

            var ray = eventCamera.ScreenPointToRay(eventData.position);
            float dist = eventCamera.farClipPlane – eventCamera.nearClipPlane;

            var hits = Physics.RaycastAll(ray, dist, finalEventMask);

            if (hits.Length > 1)
                System.Array.Sort(hits, (r1, r2) => r1.distance.CompareTo(r2.distance));

            if (hits.Length != 0)
            {
                for (int b = 0, bmax = hits.Length; b < bmax; ++b)
                {
                    var result = new RaycastResult
                    {
                        gameObject = hits[b].collider.gameObject,
                        module = this,
                        distance = hits[b].distance,
                        worldPosition = hits[b].point,
                        worldNormal = hits[b].normal,
                        screenPosition = eventData.position,
                        index = resultAppendList.Count,
                        sortingLayer = 0,
                        sortingOrder = 0
                    };
                    resultAppendList.Add(result);
                }
            }
        }

 

源码下载地址:http://pan.baidu.com/s/1hqYX2Ry 

【按住Alt + 鼠标。 到Cube上后,2s触发“Selected”事件】

 

参考英文:Gaze Fuse Buttons in Unity

发表评论

电子邮件地址不会被公开。 必填项已用*标注