自从上次写完这个系列的第三篇,忙了一阵子的项目,忙了一阵子的英语,考完一大波考试之后,终于能继续给大家分享一些开发心得了,这期间有好几个同学给我私信甚至qq我,问我啥时候更新,无奈实在是太忙,只能一拖再拖,我感觉是十分对不起大家的,没能及时更新,这里给大家说个对不起。不过能有这么多人关注我的博客,这也是对我最大的肯定,能得到大家的认可心里十分的高兴,希望大家能继续关注我,我一定会陆陆续续的把我自己的一些经验心得认认真真的去整理分享给大家的~
另外,关于Cardboard SDK for Unity的英文版API我已经分享在了我的博客里,我还自己翻译了一份中文版的供大家参考,以下是地址:
Cardboard Unity SDK Reference(英文版) :http://blog.csdn.net/sunmc1204953974/article/details/47157951
Cardboard Unity SDK Reference(翻译版) :http://blog.csdn.net/sunmc1204953974/article/details/49945945
其实CardBoard提供的东西都在这里了,我接下来写的内容只是帮助大家更容易的上手,还有一些我自己的经验技巧罢了。另外,这个东西还是比较新的,Google也一直在做后续的更新,我的博客只能写到这个时间点上的内容,至于最新的动态和更新,大家只能去关注谷歌的官网了~,这个网址前几篇的时候已经提到过了。
再就是除了本篇之外,我之后会写一些Cardboard虚拟现实相关的开发技巧,下面是我目前拟定的一些内容,希望对大家有所帮助:
在虚拟现实中播放视频的几个解决方案
如何在虚拟现实中高效解决视频畸变
如何在虚拟现实中快速设置屏幕常亮
如何在虚拟现实中轻松解决手机适配
如何在虚拟现实中快速获取头部数据
如何在虚拟现实中布置一个随头部移动的物体
如何在虚拟现实中实现注视读秒点击
闲话说到这里,下面继续说正事:
在上一篇文章中,我们利用了Cardboard SDK for Unity的Demo创建了一个自己的场景,也就是把自己的模型放进场景,用虚拟现实眼镜就可以进行观赏了。
我们要想利用这个Demo进行下一步的开发,就要对其有一些基本的了解,本篇将会对官方Demo进行一些解析,希望对大家能有所帮助。
导入和运行的过程第二篇已经讲得很清楚了,不清楚的同学到前面翻翻就可以了。
我们打开Assets/Cardboard/DemoScene下的DemoScene,大家也发现这个文件夹下的东西并不多,而这些就是这个Demo的全部了,仅仅只有一个脚本代码文件。
这个Demo运行之后会有这么几个功能:
运行之后,按住Alt移动鼠标模拟头部转动,按住Ctrl模拟歪脖子的时候视角的变化,点击鼠标相当于触发,可以用来操作。
把目光也就是小黄点对准方块,点击鼠标,方块会传动到一个有距离限制的球面上的随机位置
当目光注视方块,方块会从红变成绿色,当目光离开方块,方块会从绿色变回红色
在脚下有三个按钮,分别是
Reset:重新把方块放回初始位置
Recenter:重新把视角左右方向上回归中间,用于校准
VR Mode:打开或者关闭VR模式(分屏与否)
首先我们看到左侧的Hierarchy面板,这里就把DemoScene里的组件一览无疑了,一个Cube自然是那个会变色的红绿方块,一个Plane是下面的黑底方格地板,还有一个Point Light作为光源,一个Canvas下面是一个放了三个按钮的面板,熟悉Unity的同学肯定对这些再熟悉不过了。比较特殊的是一个CardBoardMain和一个EventSystem,虚拟现实的效果就是由CardboardMain这个CardBoard主摄像机搞定的,而EventSystem是与注视点(就是那个小黄点)相关的,这里我们稍后解释。
我们去仔细的看每个组件,地板和光源没啥特殊的,但是方块Cube就不一样了:
1.整个Demo唯一的代码附在了Cube身上
2.Cube带有一个Box Collider(碰撞器),这也就是为什么我们可以使用视线(那个黄点)去点击方块的原因:只有一个物体有碰撞效果,才能检测到与视线发生了碰撞,从而进行一些操作。(大家可以发现只有看到带有碰撞器的物体时,小光点才会显示出来)
3.Cube有一个EventTrigger来接收之前提到的EventSystem的事件,并用这些条件来调用方法。
我们可以从上图的Cube的Inspector窗口看到,Cube有一个EventTrigger。
EventTrigger是用来接收来自EventSystem的事件,每当接收事件时,就会调用这些方法。所以这里就比较清楚了。
Pointer Enter指的就是眼睛看到这个物体时,然后就会调用附着在Cube上的Teleport脚本的SetGazeAt(bool)方法,并且传入一个true(注意那个箭头是打上的)
Pointer Exit指的就是眼睛离开这个物体时,然后同样会调用附着在Cube上的Teleport脚本的SetGazeAt(bool)方法,并且传入一个false(注意那个箭头是没打的)
Pointer Enter指的就是用黄点点击了这个物体(这里就是点击看着Cube点击鼠标或者触摸屏),然后就会调用附着在Cube上的Teleport脚本的TeleportRandomly方法,顾名思义就是转移到一个随机的位置
顺藤摸瓜,接下来当然是看看Teleport的代码了,看看这几个方法到底是啥:
这里我对这个类加了注释,应该写的很清楚了:
下面我贴的这个代码可能和实例里的有点区别,我加了几个大家可能比较常用的方法,比如关掉中间那条白线,关掉设置按钮的方法,大家读代码的时候可以留意一下
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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))]
/* * 瞬移类 cube的脚本代码 */
public class Teleport : MonoBehaviour
{
//定义开始的位置向量
private Vector3 startingPosition;
/* * start()方法 * 如果脚本实例是enabled的,则Start函数在第一帧更新之前被调用,在脚本实例生命周期中仅被调用一次 */
void Start()
{
//获得当前位置
startingPosition = transform.localPosition;
//设置为false关闭线
Cardboard.SDK.EnableAlignmentMarker = true;
//设置为false关闭设置按钮
Cardboard.SDK.EnableSettingsButton = true;
//设置脖子仿真效果为最大
Cardboard.SDK.NeckModelScale = 1f;
//初始化注视状态为false
SetGazedAt(false);
}
/* * SetGazedAt(bool gazedAt)方法 * 根据是否凝视方块改变方块的颜色 */
public void SetGazedAt(bool gazedAt)
{
GetComponent<Renderer>().material.color = gazedAt ? Color.green : Color.red;
}
/* * Reset()方法 * 将方块位置设置为初始位置 * 由ButtonCanvas -> Panel -> ResetButton调用 */
public void Reset()
{
transform.localPosition = startingPosition;
}
/* * ToggleVRMode()方法 * 切换VR模式 * 由ButtonCanvas -> Panel -> VRModeButton调用 */
public void ToggleVRMode()
{
//打开关闭VR模式
Cardboard.SDK.VRModeEnabled = !Cardboard.SDK.VRModeEnabled;
}
/* * TeleportRandomly()方法 * 将方块位置设置为随机位置 * 由Cardboard.SDK.Triggered && isLookedAt调用 */
public void TeleportRandomly()
{
//返回半径为1的球体在表面上的一个随机点
Vector3 direction = Random.onUnitSphere;
//static function Clamp (value : float, min : float, max : float) : float
//限制value的值在min和max之间, 如果value小于min,返回min。 如果value大于max,返回max,否则返回value
direction.y = Mathf.Clamp(direction.y, 0.5f, 1f);
// Random.value 返回一个随机数,在0.0(包括)~1.0(包括)之间
// 返回1.5 ~ 3.5 之间的随机数
float distance = 2 * Random.value + 1.5f;
// 位置为半径为1.5~3.5的球面上的随机点
transform.localPosition = direction * distance;
}
}
所以这里大家就可以理解为什么看到Cube的时候会变绿,而眼睛离开会重新变红了吧,随机传送也一目了然。
然后这个类里面的另外几个方法,就是通过脚底下的几个按钮来调用的,大家点击这三个按钮,就可以在右侧的Inspector窗口看到他们分别调用了绑定在Cube上的Teleport脚本的ToggleVRMode(),Reset(),以及Carboard的Recenter方法。
ResetButtonResetButton调用了Teleport的Reset()方法,将方块传送回初始位置
RecenterButtonRecenterButton调用了Cardboard的Recenter()方法,重新校准”前方”,比如你坐在电脑桌前看到的是正前方,你的朋友坐在你的背后和你背对背,他戴上眼镜看到的是场景的正后方,点击这个按钮之后,将会将场景正前方的位置校准为目前的实际朝向,你的朋友就会看到正前方了,而你再拿回眼镜的时候看到的将是正后方。
Cardboard类中的Recenter方法:
// Reset the tracker so that the user's current direction becomes forward.
public void Recenter() {
device.Recenter();
}
VRModeButton
VRModeButton调用了Teleport的ToggleVRMode()方法,打开/关闭VR模式,所谓打开VR模式就是上面我们看到的那种双眼双屏效果,而关闭则会变为单屏,就是下图这种效果:
到这里整个Demo的功能实现就告一段落了,大家对这个Demo应该已经看得比较透彻了,接着Demo的思路大家就可以比着葫芦画瓢,以这个Demo为基础继续自己的开发了,本篇的篇幅也不短了,就写到这里吧,希望对大家有所帮助。
总结一下就是CardboardMain作为CardBoard提供的主摄像头,实现了虚拟现实的效果,这里大家看文档的话会有更深的理解,而且也会看到谷歌在背后做的工作还是很多的,像是畸变的处理等等复杂问题,谷歌已经帮我们做好了,再比如后续我会讲到关于这个主摄像头的用法,里面已经封装好了很多方法供我们使用,比如可以适配不同手机等等。再就是Demo中的EventSystem与Head下的GazePointer提供了注视点的一系列接口,我们可以用EventTrigger来使用这个注视点作为虚拟现实中的三维鼠标去做一些事情,也可以去自定义注视点,这些我都会在后续中仔细讲解。
这个系列的目的一是我自己在网上查资料的时候发现没有什么资料,所以分享出来帮助大家,另外就是个抛砖引玉的作用,相信对Unity比较熟悉的同学,基于谷歌做的这些工作,很快就可以开发出很赞的虚拟现实应用了~
这个插件还是有一些问题的,我开发的时候就遇到了不少,比如有时候陀螺仪会乱飘,API提供的获取头部数据的方法获取回来的数一直不变,在后续中我会尽量把这些问题的解决方案分享给大家,还希望大家继续关注我,谢谢~