由于在开发中遇到的问题需要较大的文字量描述,特此介绍开发的整个流程,并用红色标记所遇到的问题以及解决方法。
开发流程如下:
1. 下载游戏所需模型与素材并导入Unity。
2. 添加玩家飞机
在素材中添加玩家的飞机到层级视图(Hierarchy)中,并命名为player。层级视图 (Hierarchy) 包含当前场景中的每个游戏对象 (GameObject)。有些是三维模型等资源文件的直接实例,其余是预设 (Prefabs) 实例,自定义对象构成游戏的绝大部分。预设 (Prefab) 是一种资源,存储在工程视图 (Project View) 中可重复使用的游戏对象 (GameObject)可在层级视图 (Hierarchy) 中选择对象并将一个对象拖到另一个对象内,以应用父子化 (Parenting)(见下图)。在场景中添加和删除对象后,还将在层级视图 (Hierarchy) 中显示或消失。
查看游戏对象的时候,可以使用QWER几个快捷键进行观察视角的旋转、移动和缩放。
鉴于飞机大战游戏中会涉及到碰撞等事件的发生,而飞机模型由太多的三角形组成,做碰撞检测时会导致效率不高的问题产生。因此,我们在player中加一个飞机碰撞模型,并添加到飞机模型的网格碰撞器(mesh collider)中。
同时,由于飞机本身存在重力,运行之后会在所在的三维空间中自由落体,而我们要让飞机在一个平面的运动,因此我们在player的刚体性质(rigidbody)中取消重力影响。
最后,我们给player加上喷火模型,并调整喷火模型的位置。飞机模型便制作完成
3. 摄像机设置
摄相机(Camera)是向玩家捕获和显示世界的设备。摄像机的默认配置并不符合这种横版游戏的玩家视角,因此我们对摄像机的参数进行调整。首先,默认的摄像机投影(Projection)是透视(Perspective)的,即摄像机(Camera)将使物体和透视完好无损。我们需要把它调为正交(Orthographic)的,即相机会均匀地渲染物体,没有透视感。其次,默认的摄像机背景是蓝色的,不符合太空是黑色的这样的认知,因此进行相应调整。最后,我们把相机视角设置为俯视飞机,类似于经典的雷电游戏的视角。
4. 添加灯光效果
经过前几步之后,我们发现飞机和场景的颜色非常暗,因此我们要设置灯光从而美化游戏界面。根据调整,我们设置了三个灯光,使飞机达到一个比较好的效果。
5. 添加背景
在层级视图(Hierarchy)中添加一个Quad对象,命名为Background。Quad对象是由两个三角形构成的四边形,用于贴图。调整Quad的参数,使它置于player的正下方,并添加素材中的背景图片。根据素材图片本身的像素大小调整背景的大小以及飞机相对于背景的相对位置。
创建一个GameController脚本,用于整个游戏的初始化、重新开始、界面提示文本、计分功能、场景控制等。
6. 玩家飞机控制
为玩家创建一个PlayerController脚本,进行一系列操作的设置。
①移动
设置一个飞机的速度,再分别获得水平方向与竖直方向的两个值h和v。令飞机刚体Rigidbody的值为速度乘h或v。
②移动范围
飞机的移动范围必须在背景范围内,在脚本中加入一个序列化的bound类,设置xMin,xMax,yMin和yMax四个值,并根据背景图在三维空间中的参数取值。序列化属性可以让我们植入一个类用替代内容在检视面板中,从而可以在unity界面进行移动范围的设置,而无需再脚本中重新设置,提高了修改的便捷性。设置飞机刚体Rigidbody的位置,使用Mathf.Clamp函数限制value的值在min和max之间, 如果value小于min,返回min。 如果value大于max,返回max,否则返回value,从而控制飞机的移动范围在背景范围内。
③创建子弹
在层级视图(Hierarchy)中添加一个子弹bolt对象,从素材中选中激光效果作为子弹的模型加入Quad中,并调整Quad位置使得子弹在飞机发射口处。创建一个Mover脚本,类似于设置飞机的移动,我们设置子弹只在y方向上有速度,并比飞机y方向的速度快。由于子弹会击打物体,因此我们同样为子弹设置碰撞检测,为子弹设置碰撞模型,并添加子弹模型的网格碰撞器(mesh collider)中。
同时,我们给子弹添加刚体,并去除重力。
鉴于子弹在碰到物体时会引发爆炸等事件,因此我们设置子弹的isTrigger属性。如果勾选了该属性,那么该物体就是一个虚体,有形而无实,不受力的作用,其它对象可以穿过它,但是如果这时满足碰撞事件产生条件,那么该物体就会产生触发事件。
最后,将bolt对象加入预设 (Prefabs)实例中,以便于重复使用。
④发射子弹
使用时将子弹添加到玩家飞机下,在PlayerController脚本中进行设置,当按下鼠标左键的时候,发射子弹。同时,我们设置一个发射频率和下次发射时间。记当下次发射时间大于等于允许的发射间隔时,便允许发射子弹,从而控制子弹发射频率。
⑤飞机爆炸
原理同后面陨石爆炸。
7. 边界设定
由于子弹发射之后会创建越来越多的实例而不会自动消失,因此我们要在子弹所在的平面上设置一个Cube对象作为边界,当子弹超出边界时,则销毁子弹。
创建一个DestroyByBoundary脚本,当子弹碰撞器离开边界触发器时,调用OnTriggerExit,在该函数中销毁子弹。
8. 系统陨石控制
①创建陨石
陨石是玩家要躲避和攻击的“敌人”。我们选取三种不同形状的陨石加到素材中:
在层级视图(Hierarchy)中添加三个陨石对象,放置于与飞机相异的一侧,并进行类似于飞机和子弹的刚体、触发等设置。为了让游戏场景更加逼真,我们设置陨石可以进行随机旋转。创建一个RandomRotater脚本,设置陨石旋转的角速度,并使用Random.insideUnitSphere返回半径为1的球体内的一个随机点,达到随机旋转的效果。
同时,陨石应该具有与子弹相反的速度,因此我们将Mover脚本赋给陨石对象,并设置陨石运动的速度。
②陨石爆炸
当陨石碰到飞机和子弹的时候,都会发生爆炸。创建一个脚本DestroyByContact,当碰撞器碰到触发器时,调用OnTriggerEnter。如果有其他物体碰到陨石,则销毁其他物体与陨石自己。在运行时,我们会遇到刚开始游戏陨石便销毁了的问题,这是因为陨石一开始便处于boundary中,因此会同时将boundary和陨石自身销毁。因此,我们为boundary添加一个标签Tag,并在脚本DestroyByContact中加入判断条件,如果碰到的是Boundary,则直接返回,不销毁任何物体。
创建一个陨石爆炸效果的对象,当陨石销毁时,产生爆炸效果。
将该脚本添加到三个陨石的属性中。
③陨石出现
在GameController脚本中创建一个陨石的数组。借助随机数来选择出现哪一种陨石。在Update函数中,控制随机数小于某个值,从而控制陨石在x方向上有一定空间间隔地出现。
我们在Unity协程(Coroutin)方法中使用 yield return,是为了返回 IEnumerator对象,只有当这个对象的MoveNext() 返回 false 时,即该 IEnumertator 的Current 已经迭代到最后一个元素了,才会执行yield return 后面的语句。也就是说,yield return被会“翻译”为一个IEnmerator对象。
使用这个特性,我们使用循环控制每一批次“陨石进攻”时出现的陨石数量,并在循环中设置等待,即在一批陨石中,每隔一个时间段出现一个陨石。在每个出现批次之间以及游戏刚开始的时候,也设置一定时间的等待。
9. 声音
①陨石爆炸
从素材中添加陨石爆炸的音效,并勾选Play On Awake,即爆炸效果出现时播放爆炸声音。将爆炸音效添加到三个陨石中。
②背景音乐
同上,放置到GameCotroller中,即游戏一开始便播放音乐,并设置为循环播放。
③发射子弹
在PlayerController脚本中设置fire变量,在发射子弹时播放音效。并进行同上的操作。
10. 销毁爆炸效果
创建DestroyByTime脚本,为爆炸效果设置生命周期,超过生命周期就销毁。
11. 界面文本及其相关功能
创建UI Text,更名为Display Text。。
①计分功能
在GameController脚本创建计分功能。因为击中陨石才会加分,而判断陨石是否被击中是在DestroyByContact脚本中得到的,因此我们在该脚本中设置GameController object,实现对于GameController的寻找,从而获取是否击中陨石的信息。在检视面板中对击中不同的陨石的分数进行不同的设置。
②游戏结束
游戏结束时,我们要告诉玩家游戏结束了,并告诉他重新开始的方法。
在GameController脚本中进行相应的文本显示设置。同时,在生成陨石的函数中设置中断,即当游戏结束的时候不再生成陨石。
在DestroyByContact脚本中,当陨石碰到了玩家,则调用GameController结束游戏。
③重新开始
在GameController脚本中,当游戏结束且玩家按下R键时,则调用应用的LoadLevel函数重新开始游戏。
马亿
来源:https://www.cnblogs.com/mamengyiyi/p/6445590.html