Cardboard VR开发,Gaze操作实现VR的目选效果
发表于2018-05-12
CardBoard应该是目前VR市场上最廉价的”VR头显”,虽然它廉价,但并不会阻碍大家针对Cardboard开发相应的VR应用,下面就来看看通过Gaze操作实现VR的目选效果。
由于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