虚拟现实与数据可视化课程设计1东南大学仪器科学与工程学院虚拟现实与数据可视化Unity课程设计设计名称:TankWar院系名称:仪器科学与工程学院测控技术与仪器小组成员:支康仪22012235石彦飞22012216张桐22012213朱雨婷22012207张琦22012206指导老师:孙立博报告时间:2015年01月04日虚拟现实与数据可视化课程设计2目录1、前言............................................31.1作品名称...................................................31.2作品成员和分工.............................................31.3指导老师...................................................31.4作品简介...................................................32、系统方案........................................42.1使用说明...................................................42.2设计方案...................................................42.2.1场景的制作以及坦克模型的导入.........................42.2.2坦克移动,子弹效果以及MouseLook的实现...............62.2.3AI的实现...........................................82.2.4游戏场景切换的实现..................................103、课程设计总结...................................114、参考文献........................................125、附录部分........................................125.1小组成员分工...............................................125.2作品效果图................................................13虚拟现实与数据可视化课程设计31、前言1.1作品名称TankWar1.2作品成员和分工成员院系学号支康仪仪器科学与工程学院22012235石彦飞仪器科学与工程学院22012216张桐仪器科学与工程学院22012213朱雨婷仪器科学与工程学院22012207张琦仪器科学与工程学院22012206主要工作主要负责人Level3的制作以及各个脚本的编写支康仪交互界面(两个切换,胜利,失败,以及菜单界面)和ppt的制作石彦飞张桐场景1的制作以及素材的收集朱雨婷场景2的制作以及报告的撰写张琦1.3指导老师孙立博仪器科学与工程学院1.4作品简介游戏是娱乐生活的重要部分,对于缓解压力有着极大的作用。而坦克大战作为我们童年的经典的一款游戏,其已经带给我们难以忘怀的回忆。通过这学期虚拟现实课程的学习,我们小组将unity3d与射击游戏相结合,制作了一款精彩纷呈的3D坦克大战游戏,整个过程将所学的知识与实践相结合,帮助我们对于unity3d的应用有了更深的了解。我们设计的这款名为TankWar的3D坦克大战游戏一共分为三关。第一关设置的是荒漠场景,给人一种苍凉的感觉,我方坦克和敌方坦克在一望无际的荒漠上激战,实在是让人酣畅淋漓。第二关设置的是沼泽森林,同样的作战手法不同的环境也让人耳目一新。最后一关双方坦克开进了人们所生活的城市,在高楼林立中展开一场激战。三个关卡的难度逐渐增加,梯度合理,让人想挑战且欲罢不能,具体难度设置可从下表看出:虚拟现实与数据可视化课程设计4项目关卡血值耗血量/被击中一次需杀敌数第一关30001005第二关200010010第三关1000100152、系统方案2.1使用说明1)开发环境:Unity3D2)操作方法(按键控制)调整对象对应按键对应效果玩家坦克方向键up-↑或w坦克前进方向键down-↓或s坦克后退方向键left-←或a坦克向左转方向键right-→或d坦克向右转鼠标左键发子弹鼠标旋转坦克向相应方向旋转ESC退出游戏回到主菜单2.2设计方案2.2.1场景的建立整个游戏分成三关实现,所以需要绘制三个场景。第一个场景是荒漠,第二个场景是森林,我们使用上课学过的unity3d中建立地形的方法,第一关和第二关均是自己绘制的。最后一关我们想寻求新意,于是从网上下载了一个城市的3d模型导入建好的场景里边,并通过在建筑物上加cube来给其中的建筑物赋予了rigidbody这一物理属性使其可以检测碰撞等。第一关最后在场景面板中(俯视):在游戏面板中显示如下:虚拟现实与数据可视化课程设计5第二关展示:第三关:以上是我们游戏的三个场景,因为坦克大战并不需要赛道之类的东西,所以其实场景绘制还是比较简单,我们基本上是利用unity3d自带的资源包,只在第一关中导入了一些岩石模型以及荒漠的纹理图片,当然,第三关也是导入模型并给其添加物理属性。整个游戏场景的制作到此基本完成。2.2.2坦克模型的导入敌方坦克和玩家坦克均是通过导入模型建立起来的,这些模型是我们从网站上搜寻的资源。坦克的构成由几个部分组成,为了实现鼠标控制视角的功能,我们还在坦克中内置了一个摄像头,以及为了实现坦克开前灯的效果我们在坦克中添加了一个点光源。我们可以从层次面板中看到:虚拟现实与数据可视化课程设计6坦克的具体组成部分如下:玩家坦克:其中炮筒如下:坦克基座如下:再加上光源,相机,以及连接炮筒和基座的两个cube(为了使得炮筒旋转),最后给坦克模型加上rigidbody这一物理属性,整个坦克模型就制作完成了。为了在游戏中能区分敌我,增加游戏的可玩性,敌方坦克与玩家坦克造型略有不同,但是制作和导入方法相似,最后的敌方坦克我们做成如下:完成了玩家坦克的导入后,下面所进行的工作即为给坦克添加脚本来实现复杂的功能。2.2.2坦克移动,子弹效果以及MouseLook的实现2.2.2.1坦克的移动移动是坦克作战中最为基础的部分,为了实现这个功能,我们给坦克添加了一个TankMover的虚拟现实与数据可视化课程设计7脚本,其中实现移动的代码如下:this.transform.Rotate(newVector3(0,Input.GetAxis(Horizontal)*TurnSpeed*Time.deltaTime,0));this.transform.position+=this.transform.forward*Input.GetAxis(Vertical)*Speed*Time.deltaTime;主要Input.GetAxis这个函数来获取移动或是旋转的方向(响应键盘按下的键值,这一部分在unity中已经集成好的)并乘以相应的速度和时间,分别控制坦克前进后退以及左右旋转。其中speed是我们之前所设定的值,水平方向则旋转,垂直方向则前进后退。2.2.2.2鼠标控制视角实现这个函数实现的比较复杂,我们参考了unity3d自带的第一人称控制的相关代码并修改了有关参数。这里只截取其中关键的一部分来进行简单说明:主要是通过枚举来实现三种情况的鼠标控制:if(axes==RotationAxes.MouseXAndY)//可以上下左右旋转{floatrotationX=transform.localEulerAngles.y+Input.GetAxis(MouseX)*sensitivityX;rotationY+=Input.GetAxis(MouseY)*sensitivityY;rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);//限定在最大最小值之间transform.localEulerAngles=newVector3(-rotationY,rotationX,0);}elseif(axes==RotationAxes.MouseX)//只能左右旋转{transform.Rotate(0,Input.GetAxis(MouseX)*sensitivityX,0);}else//只能上下旋转{rotationY+=Input.GetAxis(MouseY)*sensitivityY;rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);transform.localEulerAngles=newVector3(-rotationY,transform.localEulerAngles.y,0);}代码中共枚举了鼠标变化的三种状态,分别给出相应的旋转角度,方向等。通过获取鼠标变化的方向再乘以相应的灵敏度来得到变化的角度,并通过transform域操作来更新坦克的状态。2.2.2.3发弹效果实现本游戏中控制坦克发弹主要通过两个函数WeaponController和WeaponLauncher来实现,WeaponLauncher中又调用了shoot函数来控制炮弹发射间隔时间以及数量(AI中敌方坦克是自行发射炮弹的),通过不断对炮弹这一预设进行实例化,当检测到碰撞时给对象造成一定的伤害值,并且炮弹自身会消失,从而形成整个坦克发射炮弹系统。炮弹实例化部分代码:if(Muzzle){GameObjectmuzzle=(GameObject)GameObject.Instantiate(Muzzle,missileposition,missilerotate);muzzle.transform.parent=this.transform;GameObject.Destroy(muzzle,MuzzleLifeTime);if(MissileOuter.Length0){muzzle.transform.parent=MissileOuter[currentOuter].transform;}}虚拟现实与数据可视化课程设计8for(inti=0;iNumBullet;i++){if(Missile){Vector3spread=newVector3(Random.Range(-Spread,Spread),Random.Range(-Spread,Spread),Random.Range(-Spread,Spread))/100;Vector3direction=this.transform.forward+spread;GameObjectbullet=(GameObject)Instantiate(Missile,missileposition,missilerotate);if(bullet.GetComponentDamageBase()){bullet.GetComponentDamageBase().Owner=Owner;}if(bullet.GetComponentWeaponBase()){bullet.GetComponentWeaponBase().Owner=Owner;bullet.GetComponentWeaponBase().Target=target;}bullet.transform.forward=direction;if(RigidbodyProjectile){if(bullet.rigidbody){if(Owner!=null&&Owner.rigidbody){bullet.rigidbody.velocity=Owner.rigidbody.velocity;}bullet.rigidbod