Cardboard VR开发,Gaze操作实现VR的目选效果

发表于2018-05-12
评论0 1.9k浏览
CardBoard应该是目前VR市场上最廉价的”VR头显”,虽然它廉价,但并不会阻碍大家针对Cardboard开发相应的VR应用,下面就来看看通过Gaze操作实现VR的目选效果。

一、首先是下载unity SDK,可以进入Google Cardboard官方网站的开发者指南页面查找下载:https://developers.google.com/cardboard/unity/download下载后导入到unity中可以查看官方的demo,如下图:

由于Cardboard没什么按键,所以选择之类的事情只能用目选来进行,那怎么实现目选呢?可以想象一下,目选无非就是两部分,a:旋转读条;b、确认选择。
但是有一点,两部分分开来做那很简单啦,但是怎么放到一起呢?

首先,我们先来看看该部分原本给你提供的代码:Teleport.cs
// Copyright 2014 Google Inc. All rights reserved.  
//  
// Licensed under the Apache License, Version 2.0 (the "License");  
// you may not use this file except in compliance with the License.  
// You may obtain a copy of the License at  
//  
//     [url=http://www.apache.org/licenses/LICENSE-2.0]http://www.apache.org/licenses/LICENSE-2.0[/url]  
//  
// Unless required by applicable law or agreed to in writing, software  
// distributed under the License is distributed on an "AS IS" BASIS,  
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
// See the License for the specific language governing permissions and  
// limitations under the License.  
using UnityEngine;  
using System.Collections;  
[RequireComponent(typeof(Collider))]  
public class Teleport : MonoBehaviour, ICardboardGazeResponder {  
  private Vector3 startingPosition;  
  void Start() {  
    startingPosition = transform.localPosition;  
    SetGazedAt(false);  
  }  
  void LateUpdate() {  
    Cardboard.SDK.UpdateState();  
    if (Cardboard.SDK.BackButtonPressed) {  
      Application.Quit();  
    }  
  }  
  public void SetGazedAt(bool gazedAt) {  
    GetComponent<Renderer>().material.color = gazedAt ? Color.green : Color.red;  
  }  
  public void Reset() {  
    transform.localPosition = startingPosition;  
  }  
  public void ToggleVRMode() {  
    Cardboard.SDK.VRModeEnabled = !Cardboard.SDK.VRModeEnabled;  
  }  
  public void ToggleDistortionCorrection() {  
    switch(Cardboard.SDK.DistortionCorrection) {  
    case Cardboard.DistortionCorrectionMethod.Unity:  
      Cardboard.SDK.DistortionCorrection = Cardboard.DistortionCorrectionMethod.Native;  
      break;  
    case Cardboard.DistortionCorrectionMethod.Native:  
      Cardboard.SDK.DistortionCorrection = Cardboard.DistortionCorrectionMethod.None;  
      break;  
    case Cardboard.DistortionCorrectionMethod.None:  
    default:  
      Cardboard.SDK.DistortionCorrection = Cardboard.DistortionCorrectionMethod.Unity;  
      break;  
    }  
  }  
  public void ToggleDirectRender() {  
    Cardboard.Controller.directRender = !Cardboard.Controller.directRender;  
  }  
  public void TeleportRandomly() {  
    Vector3 direction = Random.onUnitSphere;  
    direction.y = Mathf.Clamp(direction.y, 0.5f, 1f);  
    float distance = 2 * Random.value + 1.5f;  
    transform.localPosition = direction * distance;  
  }  
  #region ICardboardGazeResponder implementation  
  /// Called when the user is looking on a GameObject with this script,  
  /// as long as it is set to an appropriate layer (see CardboardGaze).  
  public void OnGazeEnter() {  
    SetGazedAt(true);  
  }  
  /// Called when the user stops looking on the GameObject, after OnGazeEnter  
  /// was already called.  
  public void OnGazeExit() {  
    SetGazedAt(false);  
  }  
  // Called when the Cardboard trigger is used, between OnGazeEnter  
  /// and OnGazeExit.  
  public void OnGazeTrigger() {  
    TeleportRandomly();  
  }  
  #endregion  
}  

其实大部分代码我都从头到尾稍稍读了一遍,其实接口已经清楚地给我们放出来了,就是这块代码。代码中有一个SetGazedAt的方法,该方法就是当你水平目视前方的物体算作你选中的物体,官方demo里是当你目视一个cube时把该cube的颜色由红色换为绿色。

二、好的,突破口已经找到了,我们来看看怎么实现旋转读条的效果:

其实很简单,研究过UI的人应该都明白,就是一个很简单的遮罩。
放一个画布canvas,然后创建一个image命名为imageBg作为背景,再创建一个image命名为imageFill作为内容,然后复制一个imageFill,选color属性调成半透明,颜色改成灰色,image Type选择Filled,大小都调合适了。然后就做成了,如图:

三、把Teleport.cs拖到imageBg上,我们再来看刚刚的代码部分,按常理来说,点击选中面板中可以直接添加一个button属性就可以实现,但是我们现在要的是目选,所以就要自己来判断了,其实也不难,也就是一个触发器的问题。
public void SetGazedAt(bool gazedAt) {  
                isStartTime = gazedAt ? true : false;  
        }  

上面这个函数前面加上public
在imageBg下添加一个Event Trigger,添加Pointer Enter和Pointer Exit,分别对应SetGazeAt方法的两个值

在初始化里获取imageFill的image组件,设置fillAmount的初始值为零。
在update里利用计时器来控制旋转读条的快慢,并在读完时刻判断目选的选中状态。
修改后的全部代码如下:
using UnityEngine;  
using System.Collections;  
using UnityEngine.UI;  
public class TeleportGUI : MonoBehaviour, ICardboardGazeResponder {  
        public float coldTime = 1;  
        private Image imagefill;  
        private float timer = 0;  
        private bool isStartTime = false;  
        private double minNum = 0.01;  
        private double maxNum = 0.02;  
        private bool isNext = false;  
        public Text index;  
        int IndexInt = 0;  
        string IndexStr = "";  
        // Use this for initialization  
        void Start () {  
                imagefill = transform.Find ("Imagefill").GetComponent<Image> ();  
                imagefill.fillAmount = 0;  
                SetGazedAt (false);  
        }  
        void LateUpdate() {  
                Cardboard.SDK.UpdateState();  
                if (Cardboard.SDK.BackButtonPressed) {  
                        Application.Quit();  
                }  
        }  
        public void SetGazedAt(bool gazedAt) {  
                isStartTime = gazedAt ? true : false;  
        }  
        // Update is called once per frame  
        void Update () {  
                if (isStartTime) {  
                        timer += Time.deltaTime;  
                        imagefill.fillAmount = (coldTime - timer) / coldTime;//从1到0减小  
                        if (timer >= coldTime) {  
                                imagefill.fillAmount = 0;  
                                timer = 0;  
                                isStartTime = false;  
                        }  
                }  
                if(!isStartTime) {  
                        timer = 0;  
                        imagefill.fillAmount = 0;  
                }  
                if (imagefill.fillAmount < maxNum && imagefill.fillAmount >minNum) {  
                        isNext = true;  
                }  
                if (isNext) {  
                        ChooseManageScript.Instance.A_Btn ();  
                        index = GameObject.Find("IndexBackground").transform.Find ("Index").GetComponent<Text> ();  
                        IndexInt = int.Parse(index.text);  
                        IndexInt += 1;  
                        IndexStr = IndexInt.ToString();  
                        index.text = IndexStr;  
                        isNext = false;  
                }  
        }  
        public void TeleportRandomly() {  
                Vector3 direction = Random.onUnitSphere;  
                direction.y = Mathf.Clamp(direction.y, 0.5f, 1f);  
                float distance = 2 * Random.value + 1.5f;  
                transform.localPosition = direction * distance;  
        }  
        #region ICardboardGazeResponder implementation  
        /// Called when the user is looking on a GameObject with this script,  
        /// as long as it is set to an appropriate layer (see CardboardGaze).  
        public void OnGazeEnter() {  
                SetGazedAt(true);  
        }  
        /// Called when the user stops looking on the GameObject, after OnGazeEnter  
        /// was already called.  
        public void OnGazeExit() {  
                SetGazedAt(false);  
        }  
        // Called when the Cardboard trigger is used, between OnGazeEnter  
        /// and OnGazeExit.  
        public void OnGazeTrigger() {  
                TeleportRandomly();  
        }  
        #endregion  
}  
来自:https://blog.csdn.net/yushengqi12345/article/details/77569658

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引