如何用Unity和Cardboard做一款手机游戏VR游戏

写给VR手游开发小白的教程:(五)Cardboard插件与Android之间的通信交互_Unity3D教程_中国AR网
&当前位置: &
上篇已经把BaseVRDevice这个类解析了一下,紧接着,摆在我们眼前的问题是既然已经完成了VR设备的基类,那后续的子类必然会对基类做一个相应的扩展,以实现Android和ios设备所独有的功能。事实上AndroidBaseVRDevice这个类就完成了这些事情,学过Android的人都知道一个app的运行最基本的就是Layout和Activity,一个控制前端一个控制后台,而我们本节所要介绍的这个类,就是在BaseVRDevice的基础上,增加了Android所特有的Java对象的创建和Activity的管理,这搭建了一个桥梁,允许我们将Unity和Android两个不同的平台进行通信和交互。AndroidBaseVRDevice.cs的代码如下,大家可以参照着看看&&1&&2&&3&&4&&5&&6&&7&&8&&9&10&11&12&13&14&15&16&17&18&19&20&21&22&23&24&25&26&27&28&29&30&31&32&33&34&35&36&37&38&39&40&41&42&43&44&45&46&47&48&49&50&51&52&53&54&55&56&57&58&59&60&61&62&63&64&65&66&67&68&69&70&71&72&73&74&75&76&77&78&79&80&81&82&83#if UNITY_ANDROIDusing UnityEngine;using System.Collections.Generic;public abstract class AndroidBaseVRDevice : BaseVRDevice {protected AndroidJavaObject cardboardActivity;public override bool SupportsNativeDistortionCorrection(List&string& diagnostics) {bool support = base.SupportsNativeDistortionCorrection(diagnostics);if (cardboardActivity == null) {diagnostics.Add(&Cannot access Activity&);}return support;}public override void Destroy() {if (cardboardActivity != null) {cardboardActivity.Dispose();cardboardActivity = null;}base.Destroy();}protected virtual void ConnectToActivity() {try {using (AndroidJavaClass player = new AndroidJavaClass(&com.unity3d.player.UnityPlayer&)) {cardboardActivity = player.GetStatic&AndroidJavaObject&(&currentActivity&);}} catch (AndroidJavaException e) {cardboardActivity = null;Debug.LogError(&Exception while connecting to the Activity: & + e);}}protected virtual bool CallActivityMethod(string name, params object[] args) {return CallObjectMethod(cardboardActivity, name, args);}protected virtual bool CallActivityMethod&T&(ref T result, string name, params object[] args) {return CallObjectMethod(ref result, cardboardActivity, name, args);}protected AndroidJavaObject Create(string className, params object[] args) {try {return new AndroidJavaObject(className, args);} catch (AndroidJavaException e) {Debug.LogError(&Exception creating object & + className + &: & + e);return null;}}protected static bool CallObjectMethod(AndroidJavaObject jo, string name, params object[] args) {if (jo == null) {Debug.LogError(&Object is null when calling method & + name);return false;}try {jo.Call(name, args);return true;} catch (AndroidJavaException e) {Debug.LogError(&Exception calling method & + name + &: & + e);return false;}}protected static bool CallObjectMethod&T&(ref T result, AndroidJavaObject jo, string name,params object[] args) {if (jo == null) {Debug.LogError(&Object is null when calling method & + name);return false;}try {result = jo.Call&T&(name, args);return true;} catch (AndroidJavaException e) {Debug.LogError(&Exception calling method & + name + &: & + e);return false;}}}#endifAndroidBaseVRDevice.cs/**************************************************************************************************************************************/代码的第一句就给我们摆了难题,AndroidJavaObject这个类看着像是Android的,但事实上它是Unity库里的一个类,见圣典:发现这个类下,有一系列函数和一个构造方法static function AndroidJavaObject (className : string, params args : object[])这个构造方法很有趣,它有两个参数分别是1、指定的Java类名2、传递的参数为什么说他有趣?大家可以看一个例子//创建一个java.lang.String对象,持有该字符串&some string&function Start() {var jo = new AndroidJavaObject(&java.lang.String&, &some string&);}这是摘自圣典的一个例子,我们通过构造函数将AndroidJavaObject实例化了以后,生成的居然不是AndroidJavaObject的实例而是其字符串参数java.lang.String对象的一个实例。这很神奇,因为我们通常所能认识到的是构造函数构造的一定是类本身,那为什么这里不是?事实上,我们构造出来的仍然是本身,只不过“看起来”不一样而已。什么是“看起来”不一样呢?从这里需要引申到Java中所有对象的祖先类,Object类,这里的AndroidJavaObject就是Object类的一个泛型,关于Object类的概念,给一个链接这里不再详述好了,现在Object作为泛型类,把AndroidJavaObject这个类作为参数来确定具体实例化哪个对象,而实例化哪个对象的问题,就由实例化的AndroidJavaObject类来解答了,所以说,不管是最终实例化的java.lang.String类,还是我们觉得应该实例化的AndroidJavaObject类,都是产自于Object类,它们事实上来源是相同的,而我们只是通过泛型这种手段来将Object对象做了个“变形”。理解了这一步,我们就知道AndroidJavaObject类在Unity中存在的意义了,它就像一座桥梁,将Java对象与远方的Unity中的对象联系起来。/**************************************************************************************************************************************/AndroidJavaClass player = new AndroidJavaClass(&com.unity3d.player.UnityPlayer&//同理AndroidJavaClass也是如此,只不过它联系了Java中的类和Unity中的类。需要说明的一点是,Class类没有公共构造方法,我们都知道类是对象的抽象,而Class是对Java中所有类的一个抽象,它保存的是一个Java类的元信息,负责类的类型标识问题而从不负责类的实例化问题。于是,我们知道AndroidJavaClass的实例得到的是指定的类型,而不是实例化的对象。附上圣典的介绍:/**************************************************************************************************************************************/解决了这个问题,让我们接着往下using (AndroidJavaClass player = new AndroidJavaClass(&com.unity3d.player.UnityPlayer&))//这一步相当于在Java中引用了名为com.unity3d.player.UnityPlayer的库,而C#与Java互通上面已经说了,一句话就是C#中创建的Java对象需要用到添加到Java语言中的com.unity3d.player.UnityPlayer库中的操作,听起来有些拗口。cardboardActivity = player.GetStatic&AndroidJavaObject&(&currentActivity&);//然后我们接着调用AndroidJavaClass 类下的GetStatic.&FieldType&方法去获取当前的Activity,这句话如果在上一句之前是无法执行的,因为GetStatic.&FieldType&语句是Unity库里的语句,我们正是通过添加了com.unity3d.player.UnityPlayer库才使得该语句可用。说到这里又有人会问了,我们开头的using UnityEngine不是已经将Unity库导入进来了吗?其实using UnityEngine只是将Unity和C#联系起来,但是我们现在做的,是C#环境中,实现Android和Unity的通信,两者显然不一样。哈哈,这就是编程的魅力:无限的扩展性+严密的逻辑性!/**************************************************************************************************************************************/接下去调用对象方法的一些函数和Creat新的对象就不再详述了,无非就是用泛型实现对象内调用其他对象方法,相信大家都能看懂
中国AR网(www.chinaar.com)为更好的服务国内AR技术爱好者 ,现已推出“AR网”官方公众号,请在微信公众账号中搜索「AR网」或者加QQ群:,即可获得每日内容推送和最新的AR开发教程及AR H游戏资源哦!
上一篇: 下一篇:
E1321日额日社会小猪日日123日上传时间:
「Google Cardboard 开发」04.创建Unity项目
专辑名称:
专辑创建者:
视频数:33
VR(虚拟现实)教程,欢迎一起讨论学习!
56官方微信
扫一扫发现精彩解析如何使用Unity3D开发一款VR弹球游戏
开发VR游戏首先要选择一个合适的平台。目前可供选择的平台不多,Google的Cardboard和OculusRift等头戴式显示设备都是可供选择的对象。但Cardboard的价格低廉,市场占有率更高,用它来作为移动端进行开发更为划算一些。当然,选择其一并不代表我们舍弃了其它开发平台的优点,同时Unity3D游戏引擎拥有跨平台的特性,对项目经过简单的修改便可将VR项目移植到PC或者其他平台中。
使用Unity3D开发VR游戏十分便捷:
首先在于如场景、模型等丰富的素材资源,开发者们无需再为美工建模这些相对耗时间的工作而困扰。
其次在于便捷的引擎支持,OculusRift、GoogleCardboard和HTCVive等产品均提供了对于Unity3D引擎的支持,只需将官方提供的插件包导入到目标项目中,便可使用相应的VR产品了。
随着Unity5.3版本的发布,Unity增强了对VR开发的兼容性,在项目设置中我们可以直接选择使用Oculus或是OpenVR进行开发。
下面就以一款简单的VR弹球游戏为例子,谈谈使用Unity3D游戏引擎开发VR游戏的流程。
先说说VR弹球游戏的规则。和传统的弹球游戏一样,在VR弹球游戏中有两个玩家,一个是用户,另一个则是AI。玩家分别控制己方的一块弹球板,当弹球碰到弹球板的时候,球则会反弹回去。如果一方没有成功反弹弹球的话则该方失败。
那么对于这款VR弹球游戏,具体应该怎样开发呢?
在确定了开发平台之后,我们需要在Unity中导入相关的SDK。如选用OculusRift则导入OculusRift的SDK,选用GoogleCardboard则导入Cardboard的SDK。这些SDK的使用方法大同小异,每个SDK中均包含着一个角色控制器,而对角色控制器的使用也近乎相同。我们将相应的SDK导入Unity,随后将SDK中的角色控制器拖放到游戏场景中,进行测试。在使用OculusRift等设备进行调试的时候,往往需要将OculusRift配置好,连接电脑才能调试。而Cardboard的调试,可以使用Alt键+拖动鼠标来模拟用户头部的晃动。
在正式开发游戏之前,采用一个良好的目录结构是项目管理的有效方式。这个项目中,在根目录下有如下的目录:Model(存放OBJ或是FBX格式的模型)、Texture(存放模型的贴图,PNG等格式的图片)、Material(存放通过贴图制作的Unity中的PBR贴图)、Prefab(存放Unity预设物体)、Scene(存放游戏的场景文件)。在这种目录结构下,我们还可以对Model、Texture、Prefab和Material等目录进行细分,在一些大的项目中拥有大量的模型的时候,通过建立Environment、Building和Player等目录以细化Model目录结构,以方便对于模型的寻找,加快开发速度。在对目录中的文件命名的时候,模型文件以M_模型名称进行命名,Material以Mat_贴图名称进行命名也不失为一种良好的习惯。
开发游戏的第一步便是搭建场景。在该VR游戏中,我们选用的风格是对程序员友好的像素3D风格。像素3D建模较为简单,所有的模型都是我们团队中的程序员制作的。在像素建模的软件选用方面,我们使用了MagicaVoxel这款免费的软件。MagicaVoxel的界面和操作十分简单,即使没有基础,跟着网上的教程半个小时左右就能入门,并做出自己心仪的3D模型。在建模阶段完成之后,将模型和材质等资源按照约定的目录结构导入Unity3D中。
在搭建场景时,先将FBX或是OBJ格式的模型拖动到Scene(场景)面板中,如果在建模的时候使用的单位和Unity默认单位(米)不同的话,便需要进行相应的缩放。通常如果是场景类的模型如Terrain(地形),我们选择将模型的Position属性设为(0,0,0),这样将会对后面的脚本编写和场景的搭建工作剩下时间。在简单地对模型进行拖动之后,得到了如下效果的游戏场景。
此时搭建好的场景是静态的,无法进行互动,我们需要进行相应脚本的编写,以实现游戏的可操控性。如下图所示,我们需要编写脚本的地方有3个,一个是蓝色的击球平台,一个是粉色的击球平台,一个是蓝色的球。
在这里,我们选择使用简单的AI来控制粉色的击球平台,玩家控制蓝色的击球平台。从这些物体我们可以引申出以下三个问题:
如何移动玩家控制一方的击球平台;
如何控制电脑一方的击球平台;
如何对弹球进行反弹。
首先是如何移动玩家的击球平台。要解决这个问题,就需要确定一个输入方式。在VR游戏中有传统游戏中的使用手柄、键鼠输入,同时还有HTCVive和OculusRift的动作捕捉。但我们决定使用的输入方式是GazeInput(凝视输入)。凝视输入的原理是通过在角色控制器的摄像头射出一条射线,该射线代表玩家的视线,射线碰撞到的位置便是玩家目前凝视的位置。
在实现方面,需要在场景中新建一个Quad物体,与场景中的地面垂直,其宽度为玩家击球平台可以移动的范围,其高度可以设置为1000甚至更大。最后将该Quad的MeshRenderer关闭,并调整其位置到玩家的击球平台的位置。然后,我们需要对VR中的SDK中的角色控制器进行相应的修改,由于该弹球游戏中采用的是固定视角,因此我们需要删除SDK中的角色控制器的RigidBody等组件,仅需要能跟随玩家头部运动的Camera即可。找到角色控制器中的Camera,在其上添加如下脚本RayCaster.cs:
voidFixedUpdate()
Rayray=newRay(transform.position,transform.forward);
if(Physics.Raycast(transform.position,transform.forward,outhit))
if(hit.collider.gameObject.tag=="Quad")
hitPos=hit.point.x;
publicfloatgetHisPos()
returnhitP
在上述脚本中,定义了一个射线和射线投影碰撞。当射线投影碰撞的对象是Quad的平面的时候获取碰撞点的x坐标(因只需移动弹球平台的X坐标,所以只获取碰撞点的X坐标),并保存到hitPos变量中,以便其他脚本调用。
接着在Hierarchy(阶层面板中)找到玩家控制的弹球平台,在其上编写脚本playerMovement.cs。
GameObjectmainC
floatthisX;
voidStart()
mainCamera=GameObject.FindGameObjectWithTag("MainCamera");
rc=mainCamera.GetComponent();
thisX=this.transform.position.x;
voidFixedUpdate()
this.transform.position=newVector3(rc.getHisPos()+thisX,this.transform.position.y,this.transform.position.z);
在上述脚本中,实现了通过获取MainCamera的RayCaster组件的碰撞点坐标来相应的移动弹球平台。
至此,通过视线来控制玩家击球平台的功能已经完成。对于电脑控制的击球平台,可以通过设定其平台的移动速度来决定难度,通过预测弹球到达电脑方的位置来决定电脑移动平台的目标点。在如何反弹弹球的问题上,我们使用Unity3D自带的物理引擎,在弹球物体上增加RigidBody组件,将RigidBody的UseGravity选项取消选择,同时将Drag和AngularDrag设为0和Constraint中的FreezePosition的Y选项勾选上。这样,在游戏开始的时候,通过给弹球一个力来发球,当弹球碰到场景和击球平台的Collider的时候便会进行相应的反弹。至此,上面提出的三个问题解决完毕。
但以上三个问题都是显性的问题,解决完这三个问题后便可以对游戏进行简单的操作,并不能完成真正意义上的游戏。因为在游戏设计中,还有一些对象是隐性的,没有实际的物体形态。这些对象有GameManager(游戏管理器)、StateMachine(状态机)和UserInterface(用户界面即UI)等。
在游戏管理方面,GameManager下面有如下子Manager:AudioManager(负责游戏中音效的管理)、GameStatusManager(负责游戏的阶段状态管理)、ScoreManager(负责游戏计分的管理)和UIManager(负责游戏UI的管理)等。以GameStatusManager为例,在不同的游戏阶段中,可以进行的动作将会不同。如在游戏开始之前的准备阶段和游戏结束阶段,弹球平台和弹球不可以移动。在游戏开始之前的准备阶段,需要对弹球和击球平台进行复位操作。
通过GameManager进行游戏管理来编写游戏,可以使程序更具有面向对象的特性,对于程序的修改、调试更为直观和方便,从而减少BUG出现的几率。
关于VR游戏中的UI,大部分Unity开发者在Unity4.6之后会倾向于选择官方的UGUI。在UGUI中,UI的TEXT、Button和Image等组件均是Canvas的子物体时才能正常工作。Canvas的默认渲染模式是以屏幕空间为基准的,然而在VR模式下,左右眼的视角均在一块屏幕中渲染,由此会造成UI在整块屏幕上只渲染一次而非分别在左右眼的视角分别渲染。因此,我们需要将Canvas的RenderMode(渲染模式)调整为WorldSpace。这样,整块UI画布便成为了游戏3D世界中的物体,由此可缩放,拖动以放置到游戏中相应的位置。
至此,整个游戏制作完毕。但在发布游戏之前,还需要一些不可或缺的工作,如添加ImageEffect视觉效果,对游戏进行配乐和进行游戏的测试等,以此来提升游戏的品质。
最后想要了解更多关于VR/AR发展前景趋势,请关注扣丁学堂官网、微信等平台,扣丁学堂IT职业在线学习教育平台为您提供学习系统,通过千锋扣丁学堂金牌讲师在线录制的VR/AR在线视频教程,让你快速掌握VR/AR从入门到精通开发实战技能。
【关注微信号获取更多的学习资料】
VR视频教程
VR虚拟现实
VR在线视频
扣丁小程序
全国免费咨询热线
北京千锋互联科技有限公司版权所有
北京市海淀区宝盛北里西区28号天丰利商场4层
京ICP备号-6
Copyright (C) 2013 - 2018玩上vr了。。。
[问题点数:40分,结帖人tonyyl]
玩上vr了。。。
[问题点数:40分,结帖人tonyyl]
只显示楼主
取消只显示楼主
匿名用户不能发表回复!|为Google Cardboard构建项目_Unity虚拟现实开发实战_百度阅读
[美]乔纳森·林诺维斯
1124人在读
3.4 为Google Cardboard构建项目如果你的Google Cardboard的目标平台是Android或iOS,请阅读本节。《适用于Unity的Google Cardboard入门指南》是一个很好的切入点(更多信息请访问https://developers.google.com/cardboard/unity/getstarted)。3.4.1 配置Android环境如果你从来没在Android环境上开发过,那么需要先下载和安装Android SDK。看一下Unity手册中关于Android SDK安装的文章(http://docs.unity3d.com/Manual/android-sdksetup.html),还需要安装Android Developer Studio(或至少要安装SDK工具包)和其他相关工具,比如Java(JVM)和USB驱动程序。最好先用一个不包含Cardboard SDK的Unity项目试着构建和运行,以确保环境都准备就绪(一个只有一个立方体的场景就行),确认你知道如何把程序安装和运行在你的Android手机上。3.4.2 配置iOSUnity手册中Getting started with iOS Development指南是一个很好的切入点(http://docs.unity3d.com/Manual/iphone-GettingStarted.html)。你只能在Mac上做iOS开发,必须配置好一个苹果开发者账号(已经支付每年的标准会员费),还需要下载和安装Xcode开发工具(通过Apple Store)。......
扫描二维码,继续阅读}

我要回帖

更多关于 做一款手机游戏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信