基于Unity的3D飞行射击游戏-SpaceWarriors

起风了 Lv3

B站Demo

Demo-b站(已将演示上传至b站)

开发背景

笔者大三下学期的时候突然想毕业去搞游戏开发,于是开始学习Unity相关的知识,之所以会想开发游戏,源于笔者的美术天赋很强而且比较爱玩,哈哈哈笔者很享受开发的游戏”折磨“玩家的样子。比这大学期间断断续续一直运营者游戏服务器,诸如mc、泰拉瑞亚、求生之路、七日杀等等服务器都有开过,最多的还是mc,mc主要开一些整合包,由于群里的大佬太多,经常需要我额外修改一些难度,这时候总会引得有些菜鸡玩家吐槽(PS:当然吐槽归吐槽,吃的还是很香)。这种自己创建玩法让玩家“乐”在其中感觉很不错。当然更重要的是,笔者不想浪费美术天赋,而且过去steam上游戏玩得多了,想玩某些类型的游戏总是找不到,即使有,往往品质也一般,甚至还不如笔者开发的这个小游戏精致,这就更加激发笔者的创作心了。

所以毕设在选题时,笔者毫不犹豫和导师商讨了下,确定了Unity游戏开发方向,后续嘛也是相当顺利,笔者母校算是还不错的二本院校,但是没有游戏开发相关的课程,所以在答辩环节,老师们只能问问实现思路(PS:对比其他同学各种后台管理系统直接撞老师专业脸上,裤衩子都能扒出来)然后放一个炫酷的Demo,就顺顺利利通过了哈哈哈。(PS:这里提醒一下,虽然是小游戏但一定要做的精致,画面表现优异但切不可过于浮夸,这样给人的印象会很好)

PS:笔者目前已经不打算从事游戏行业了,游戏行业技术门槛高这点还好,笔者有信心也有耐性学下去,但是过于不稳定。如果你想去中大厂,对不起,在这里你得不到你想要的,我想你要是去问大部分游戏从业者干这一行的原因,大部分肯定回答“热爱”“想开发自己的游戏”,很遗憾,进厂得不到这些,甚至热爱很可能在套皮同质化的道路上逐渐被消磨殆尽。那你说我不进厂,我直接和几个同僚组建独立游戏开发工作室,我们几个人合伙干,这样就能开发自己想要的游戏,首先这个想法很不错,但是现实很骨感,众所周知,游戏开发是吞金兽,美术、营销发行、策划设计哪个不烧钱,好,既然这样那我们小工作室一人干整块甚至身兼多职,这样就不用花那么多钱了,那么要不要开工资,你说我们都是爱发电,即使不算工资,那你要不要活下去,活下去要不要花钱,难道你还要白天兼职晚上爱发电开发游戏?这样熬下去身体出问题怎么办?钱怎么解决…….这样的问题太多太多了,即使我们最乐观的估计,假设工作室1里每个人都有一定资金支撑下去,那么资产如果自己做,花费的时间要多得多得多。即使上面的所有问题都解决了,游戏顺利发售,好,一锤下去半点涟漪都没有,游戏没有热度,得不到玩家的喜爱。钱花了、人也燃烧了、游戏也顺利做出来了,结果没点火花,之前的努力前功尽弃,甚至还要倒贴钱。这对于游戏开发者绝对是身心上的毁灭性打击。

所以说,理想很美好,现实很骨感,当然笔者也没有完全放弃。

笔者目前的想法是闲余时间搓小游戏供大家玩,不作为正式事业,不以赚钱为目的,有时间就搓一点,那还是很快乐的。

需求分析

分析

开发背景写的已经很详细了。

需求

需要开发一款3D横版卷轴射击游戏。

开发环境

  • Unity编辑器:Unity 2022
  • 系统:Win 10
  • 代码编辑器:Visual Studio 2022
  • 贴图材质:Photoshop 2022
  • 模型:Blender
  • 托管:Plastic SCM

技术栈 & 技术介绍

Unity 引擎

Unity是当前最流行的游戏引擎,广为人熟知的王者荣耀,原神等等都是基于Unity开发。Unity结合C#编写的脚本可以实现各种游戏功能,在游戏开发中编写脚本模块是为了提高系统的扩展性和安全性,Unity自2005年发布1.0.1版本到现在的Unity6版本,经过多年的不断发展改进,已经成为业界最主流的商用引擎之一。Unity的强大跨平台性更是大大提高了开发效率,在开发完成后几乎不需要任何修改就可以打包成对应平台的适配软件[17]。它的界面主要可以分为五个部分。分别为Scene面板用于构建游戏中的场景;Hierarchy面板用于生成和管理游戏对象;Project用于存放项目资源;Inspector面板显示游戏对象的组件信息;Game面板显示场景中摄像机所看到的画面;。

Unity编辑需要从Project面板将资源拖入Hierarchy面板才能在Scene(场景)面板中编辑游戏对象,在这个过程中还需要在Inspector面板调整游戏对象的各项属性参数,同时还需要浏览Game面板查看最终效果。可以预见的是,在需要多个面板协同使用的场景下,布局也是影响开发效率的一大因素。Unity游戏引擎支持对开发界面布局的自定义,开发者可以根据自己的习惯调整Loayout布局从而提高开发效率,下面是一个Unity开发界面布局样例。

Visual Effect Graph 技术

Visual Effect Graph是Unity的一个新的特效工具,它基于节点的编辑器,大部分功能都可以通过节点编辑实现。

与传统的Partical System(粒子系统)相比更简单和更直观,同时创建的效果更好一些,但由于是在GPU计算,这导致使用VFX Graph创建的特效不受物理的影响。所以现在官方并没有让其完全取代Partical System。

在Unity的Graph编辑器中有一些通用的概念,Context代表上下文,表示各种效果应用到粒子的操作顺序,默认从上到下执行,Context里可以有多个Block;Block代表块,定义了粒子的各种属性,这些属性可以在Block中直接设置,或者由Node节点输入;Node代表节点,节点之间可以互相连接用来相互计算,将最终的结果输出给Block。

Shader Graph 技术

Shader Graph是基于可编程流水线,和VFX Graph及其类似,也是通过可视化节点编辑,开发者可以通过图形可视化的方式创建复杂的渲染效果而无需手动编写复杂的着色器代码。除了可视化编辑功能外,Shader Graph还支持实时预览,从而在开发过程中即使查看调整效果,迭代开发便捷而高效。其编辑界面如图。

Shader Graph由Blackboard、Graph Inspector、Main Preview、Vertex、Fragment,Node等节点组成。Blackboard用于创建外部属性,相当于Shader中的Properties;Graph Inspector包含节点设置和图设置两个选项卡,节点设置可以编辑节点的命名、默认值等信息;Main Preview用于预览着色器的渲染效果;Vertex是顶点着色器,顶点变换、法线切换,切线变换在这里进行;Fragment片元着色器,光照计算等过程在这里进行;Node的作用和VFX Graph的Node类似。

UGUI 技术

UGUI是Unity官方自4.6版本后推出的新UI系统,彼时Unity的GUI(Graphical User Interface)并不是很好用,因此那时候大部分开发者喜欢用付费插件NGUI开发UI界面,NGUI 是一款专门针对Unity引擎的UI插件。现在大部分开发者都转而使用UGUI,UGUI使用灵活、快速并且具有可视化编辑,对于开发者来说易于使用,方便拓展。

UGUI的UI组件必须建立在Canvas上,创建UI组建后会自动添加EventSystem对象,其负责监听用户输入。在 Unity3D中,开发者一般采用在游戏中使用Prefab反复加载、重绘、代码手动管理UI元素加载的方法。

系统需求分析

系统性需求

本系统是基于Unity引擎的横版卷轴射击闯关游戏。面向的对象主要是各年龄层次只有零碎娱乐时间且对娱乐游戏有需求的玩家群体。

时代在进步,游戏技术也在不断迭代发展,游戏内容越来越复杂,所占体积也越来越大,玩游戏所需要的时间成本越来越高。而过去那些耳熟能详的游戏逐渐淡出,但是他们所开创的玩法仍在不断发展,游戏端的开发与设计重点在于物理系统,其中包括属性系统、有限状态机、动作系统等几个部分[20]。本系统结合了传统STG游戏的玩法,利用现在游戏引擎和游戏开发技术对游戏画面和玩法做出了创新。

在游戏的开始界面,玩家可以开始剧情闯关模式,在剧情闯关模式中玩家可以选择关卡,选择完对应关卡玩家就会进入对应关卡,每一关不断生成一波又一波敌人,直到达到设定波数,Boss出现,Boss具有更多血量,可以同时发射更多弹幕,击败Boss即可通关解锁下个关卡。

玩家具有血量,能量条,一个主动技能和一个被动技能,主动技能会消耗能量,击杀敌人可以获得能量,被动技能不消耗能量但是有冷却时间,结束后会有积分结算页面。

玩家在游玩过程中可以随时暂停,返回游戏,进入设置界面或者主菜单,设置页面有各项游戏设置,下面是玩家整体用例图。

功能型需求

性能需求

对于游戏来说,优化和用户的实际体验直接相关,如果只有功能完备却没有良好的优化,游戏的体验会非常糟糕。本系统是基于Unity引擎的横版卷轴闯关游戏,有7个关卡,不同的关卡有不同的风格。本系统有11个场景,包括1个主菜单场景,1个设置场景,1个关卡选择场景,7个关卡场景,1个结算场景。由于本系统会产生大量弹幕,本质上是一款躲弹幕射击游戏,稳定的帧率是非常必要的。

界面友好需求

UI设计需要符合用户操作习惯,布局上简洁流畅易懂,操作上丝滑流畅。

画面需求

因为本系统的主要场景是太空射击,对UI和画面特效的表现都需要尽可能贴合科幻。

系统设计

系统架构设计

系统架构设计能明确系统框架和结构,本系统是基于Unity引擎的横版卷轴射击游戏,主要分为表现层,逻辑层以及服务层三层。系统架构图。

表现层与用户直接交互,向用户展示游戏界面并且提供交互的组件,本系统共有11个界面,包括游戏开始界面,关卡选择界面,设置界面,关卡界面,暂停界面,结算界面。

逻辑层负责系统的逻辑功能。包括角色移动,角色攻击,角色受击,建起道具,背景卷动,自定义弹幕,释放技能等。

服务层为本系统提供基本服务,包括渲染游戏场景,自动根据脚本的生命周期调用脚本中相应的方法,从而为上层提供支持。

系统模块设计

结合需求分析,本系统分为游戏开始,关卡选择,设置,关卡,结算五个功能模块。进入游戏包括:进入游戏,退出游戏;关卡选择模块包括:选择关卡;设置包括:设置游戏;关卡包括:角色信息、角色攻击、角色移动、物品拾起、背景卷动、自定义弹幕、释放技能;结算包括:结算分数。系统整体组成。

游戏入口模块

该模块是比较容易实现的,但却很重要,是游戏的入口。

进入游戏

首先在主界面场景使用Unity的UGUI组件构建UI界面,主要使用的组件包括Button(按钮),Panel(面板容器),Slider(滑动条),Scroll View(滚动式图),Text(文本),Image(图片)。如下主菜单界面UI。

然后为UI组件添加脚本,命名为MainMenuController,在该脚本里定义三个按钮的Click方法。在方法里调用SceneLoader中的LoadLevelSelection方法跳转到相应页面。如下主菜单序列图。

其中MainMenuController脚本负责主菜单界面UI的功能管理。SceneLoader脚本负责场景的切换,该脚本挂载在一个空物体上,并且有一个Image子物体充当渐变的幕布,如下SceneLoader切换场景活动图。

这样就可以实现切换场景的淡入淡出。

如下主界面UI活动图。

对于游戏来说交互反馈必不可少,其中包括音效,特效,动画等等,这个场景中主要涉及到动画和音效。

动画通过Animation制作,Animation是Unity自带的动画编辑器,通过Animation利用关键帧创建按钮的悬浮,高亮、正常、按下、选中,禁用动画效果。当鼠标和按钮交互式便会触发动画效果,好处之一就是有流畅的UI交互反馈。

在这里我通过Mask遮罩是按钮呈现平行四边形。通过Animation创建各个状态的动画,正常状态时按钮只显示文本,悬浮时平行四边形背景的长度和宽度缩放由0变到1,同时字体颜色逐渐变为黑色,按下时按钮会变小,选中状态就是背景有填充色,禁用为淡灰色。如下主界面按钮效果图。

由于音效制作已超出我个人能力范畴,因此音效资源通过网络获取。且由于各个场景都涉及到音效的播放,因此一个通用类管理音效非常必要,此外由于各个场景都有音效管理,这里采用持久化单例模式。

单例模式确保类只有一个实例,对于频繁使用且重量级对象来说能节省一笔可观的系统消耗。全局静态变量也可以达到这样的效果,但是静态变量不用创建实例对象就会被分配空间,如果这个对象非常消耗资源并且在程序运行中一次也没用到就会造成资源浪费。综上,单例模式随用随建可以避免不必要的浪费。

在场景切换中,原来场景里的对象会被销毁,而对于诸如音效管理这样的类来说显然多此一举,因此在单例模式的基础上使用持久化单例,避免场景切换导致的不必要的销毁生成。

创建AudioManager作为音效管理类,包含一个AudioSource(音频源)成员变量,调用AudioSource的PlayOneShot接口即可播放音频剪辑,该类包含PlaySFX和PlayRandomSFX方法,分别对于播放音频和随机播放其中一个音频,不同之处在于一个传入单一的音频数据,另一个传入音频数据数组然后随机播放其中一个。

关卡选择模块

(1)选择关卡

首先还是先构建UI界面,为了契合科幻主题,这里实现类似于科幻电影里经常见到的全息投影效果。这一部分的模型从网上获取,这个场景要用模型来模拟按钮。将模型放置好后制作全息效果着色器。

新建Shader Graph文件命名为HologramShader(全息图着色器),定义如下变量用来控制shader效果,如下全息图着色器属性。

其中,HologramTex是全息投影中的波纹材质,Tiling是波纹材质UV的缩放倍数,ScrollSpeed是卷动速度,EdgeEmissionColor是材质边缘发光颜色。

Time节点和ScollSpeed节点相乘得到偏移值传给Tilling And Offset节点的Offset属性,这样可以得到不断随时间变化的偏移值,Screen Position允许访问网格顶点或片元的屏幕位置,最终汇聚到Sample Texture 2D节点形成的效果就是图片不断卷动,这一部分形成的是全息扫描效果。如下全息图着色器扫描效果实现。

之后调整自发光效果,如下全息图着色器边缘发光效果实现。

其中Fresnel Effect(菲涅耳效应)可以设置物体边缘反射效果,菲涅耳效应的定义如下,除金属之外其他物质均有不同程度的“菲涅耳效应”。简单来说就是实现垂直于表面时反射较弱,而当视线非垂直表面时,夹角越小反射越明显。例如生活中柏油路从远处看反射就很明显。通过EdgeEmissionColor和Fresnel Effect相乘得到最终自定义颜色边缘反射,将结果传给Emission就可以实现物体边缘发光效果。

两者结合就可以形成全息效果,如下全息图着色器效果展示。

这个场景的难点在于Unity自带的UGUI难以满足画面的需求,于是写了自定义按钮挂载到GameObject对象上从而实现更复杂的效果,这样的好处是任何一个GameObject对象都可以充当一个按钮,比如一个3D模型,一个特效等等,与其说是按钮,不如说是为该GameObject添加了鼠标交互,原理是从鼠标向屏幕内侧方向发射射线检测碰撞,从而触发相关方法。

首先实现OnTargetButton类,该类定义了鼠标的基础事件,如下OnTargetButton类图。

其中UnityEvent是Unity基于C#的Event实现的,可以直接在编辑器的面板中可视化配置,而Event基于委托(Delegate)实现。委托可以视为C++的函数指针,并且委托可以绑定多个方法。这个类首先定义了鼠标事件委托,在方法中触发委托绑定的方法。

然后实现包含响应方法的响应类,如下响应类类图。

在该类的方法中定义了在触发按钮相应事件后的动作。这里我实现了当鼠标聚焦物体时物体变大,失焦后恢复。

之后定义InteroperatToRay类,在该类的Update方法里不断进行射线检测,Update是Unity生命周期中的一个阶段,游戏的每一帧都会调用一次Update方法,如下射线检测活动图。

射线检测实现的重点在于定义两个OnTargetButton对象_lastButton和_currentButtn用来记录上次和这次触发碰撞的按钮对象,通过对比这两个对象的值来判断按钮的状态。

玩家点击想要游玩且已经解锁的关卡后,会直接触发SceneLoader的LoadLevelScene方法从而跳转到相应关卡场景,如下选择关卡序列图。

设置功能模块

(1)设置相关选项

设置可以调整游戏的各项参数,包括分辨率,亮度,鼠标灵敏度,等等常规游戏设置,将具体的功能写到SettingMenuController类里,UI的click事件绑定到相关方法即可。

关卡功能模块

角色信息

本游戏是太空科幻风格的横版卷轴设计游戏,玩家要控制的主体是一艘太空战机,有玩家当然也有敌人,这些统称为角色,因为他们有一些共同的行为和属性,比如生命值,头顶的血条,受到伤害要失去生命值等等,那么依照这些共有的属性和行为,定义一个Character基类,它包含玩家和敌人都有的属性和行为。如下角色类类图;

在此基础之上,分别创建Player和Enemy脚本,这两个脚本均继承自Character,如下玩家类类图和敌人类类图。

要实现玩家状态显示在屏幕需要准备相应贴图,这里贴图用PS制作。

首先是血条UI,在Unity里利用UGUI的Image作为一个父元素,作用是用作遮罩,遮罩就像一个透孔的窗户,有孔的地方才能看到底下的图层,该元素底下有三个Image组件分别作为前图层,后图层和底图层,Unity是按顺序渲染的,简单理解就是当多个元素覆盖同一块面积时,最后被渲染的会被显示出来,所以前图层应该放最下面,调整这些图层的发光效果并设置填充模式为横向填充。起初玩家血量为100,这些图层的填充度为1,也就是完全填充,视觉上就是满血状态,形状为遮罩层透出来的形状,当玩家受伤时前图层的填充值慢慢减少到当前值,后图层在一段延时后也缓慢减少到当前值。视觉上就呈现目前游戏中常见的血条缓冲效果。底层图层是为了区分背景和血条UI的边界。

能量条UI和血条UI方法基本一致,只不过遮罩形状特殊,图层填充模式为竖直填充。

被动冷却UI也是同理,图层模式为圆形填充,取值范围1度到360度。

角色攻击

角色分为玩家和敌人,玩家的攻击相当于一个被动状态,不断发射子弹,但也不是无限制的发射,玩家和敌人一样都有一个发射间隔,玩家的发射间隔是一个固定值,而敌人则是会间隔一个范围内的随机值发射一次。发射的原理则是在发射口发射指定的子弹,要发射什么样的子弹通过编辑器提前配置好的,不同的子弹具有不同的速度、弹道以及机制。

要实现玩家发射子弹需要定义如下变量,如下开火需要的属性变量。

projectile是要发射的子弹,weaponPower是发射等级,等级越高,同一时间发射的子弹数量越多,muzzle是子弹的发射位置,这个位置可以通过在战机模型里新建空物体并挪到模型的发射口位置后取得空物体的position获取。fireInterval是每次开火的间隔,projectileLaunchSFX是子弹发射时的音效。

玩家开火通过FireCoroutine协程实现,当玩家战机处于可用状态(还有生命值)时协程会一直运行,也就是只要战机还存在着就会不断发射子弹,如下玩家开火协程流程图。

当对象可用时,协程里的循环会不断运行,通过判断发射等级来发射对应的子弹。

敌人开火通过EnemyController类实现,这个类实现了一个初级敌人AI,如下敌人控制类类图。

其核心原理和玩家的开火差不多,通过RandomlyFireCoroutine协程实现,如下敌人随机开火协程流程图。

也就是当敌人存活是不断发射子弹。

角色受击

当玩家受到伤害时,血量会减少,触发TakeDamage(float damage),同时会触发头顶血条的UpdateStats方法用于更新玩家的状态;玩家机体有一个缓慢的自动修复过程,当玩家血量不为满时触发HealthRegenerateCoroutin血量回复协程,这个协程每隔一定时间为玩家回复生命值。

敌人的受伤同玩家一样。

当敌人收到伤害是,会触发闪白效果,闪白效果通过Shader实现,在Shader中定义新的填充颜色和填充度,填充颜色设为白色,填充度设置为1就会材质就会呈现一层白色层,通过C#代码控制填充颜色和填充度可以实现自定义闪白效果。当敌人受到伤害时,填充度由0缓慢增加到设定值然后在逐渐降为0,从视觉上就呈现出闪白效果。

角色移动

玩家可以操控战机的移动并且有两种操作方式,键盘操作或者鼠标操作,战机移动时具有恒定的移动速度,同时机身还会有一定的倾斜角;

当用键盘操作时,W、A、S、D用来操作前后左右,当用鼠标操控时,战机会不断向鼠标移动。

玩家的移动控制通过Unity新版本的Input System实现,输入系统将针对一系列输入的响应策略抽象为Action(行为)。比如W对应着向前走这个行为。Action是输入系统的核心,系统通过设计Action将物理(系统如何感知设备传来的输入信号)与逻辑(系统收到信号后如何响应)进行解耦。因此在编写响应代码时,不需要考虑如何监听设备,只需要与Action进行对接即可。 Action为开发者提供了5种事件,开发者需要自定义回调函数,以委托的形式监听这些事件。C#中的委托(Delegate)类似于C++中的函数指针,是对某个方法的引用,该引用可以在运行时被改变并且一个委托可以绑定多个方法。当Action绑定的Control收到输入信号时,Action会触发事件交互事件(Started, Performed, Canceled),当Action被启用或禁用时,也会触发相应事件(Waiting, Disabled)。我定义了一个PlayerInput类用来实现玩家控制战机的脚本,通过委托监听Action。如下玩家操控移动流程图。

物品拾起

击杀敌人后,敌人会随机掉落护盾道具,道具包括护盾道具,回血道具,星星道具,回能量道具等等,护盾道具会为玩家提供一个包围战机的护盾,护盾可以承受一定的攻击且有持续时间;回血道具会回复玩家生命值,星星道具会提供额外分数加成回能量道具会为玩家回复能量值。为了和卷动的背景相协调,道具具有一个恒定向下的速度。当玩家捡起物品时会有对应的音效和一个动画,同时考虑到性能问题,道具具有一定的生命周期,这个时间取决于道具移动速度的快慢。

要实现这些功能,需要制作对应的音效,动画,脚本。动画仍旧使用Unity的Animation制作。音效从网上获取。

定义一个LootItem类用来实现道具的移动,碰撞,和玩家发生碰撞时触发捡起方法。分别定义ShieldPickUp,ScorePickUp,HealthPickUp,EnergyPickUp,StarPickUp类用来实现具体的功能,他们均继承自LootItem。如下战利品基类继承情况。

定义一个LootSetting类用于绑定道具的预制体和生成率和生成。

定义LootSpawn类,包含一个LootSetting列表用于添加要绑定的道具,该脚本挂载到敌人预制体上即可实现。

背景卷动

从物理中可以知道,选择不同的参照物对于人的感官来说具有不同的运动效果,同一个运动的情景可以因为参照物的不同而有不同的解释。玩家的战机不断的飞行,背景应该是不断运动的,既可以看做是飞机在不断移动导致的背景变化,也可以认为是背景相对于战机来说在不断卷动,在该游戏中采用背景卷动的方式。

要实现背景卷动,可以利用材质球的材质偏移实现卷动效果,建一个正方体,设置好长宽高以及缩放,将背景材质球添加到正方体上。

通过Viewport脚本实现,当场景加载时,Viewport便会开始不断运行,同时Viewpot也负责生成敌人的刷新位置。

自定义弹幕

由于本质上还是弹幕游戏,所以需要实现各种各样的弹幕,弹幕由一个个子弹组成,当子弹不断被发射,并且每次发射的方向都有所变化时会形成绚丽的效果。

要实现弹幕需要满足敌人在同一时间发射多个子弹,然后不停地重复这个过程。为敌人定义一个弹夹,数据结构使用队列实现。

释放技能

玩家的战机具有一个主动技能和一个被动技能,主动技能消耗全部能量发射一束持续性的激光,时间取决于能量值的上限,当开启激光后,能量值会不断被消耗,直到能量值为0,技能结束。被动技能是间隔一定时间发射一枚具有追踪效果的导弹,该导弹具有一个初速度和最大速度,在飞行中不断加速直到到达最大速度,同时会锁定一个敌人。

通过PS制作激光束的贴图,Shader Graph制作激光束的Shader,VFX Graph制作特效;激光束发射时,会先在机体正前方集聚能量,然后发射光束,光束持续一段时间后宽度逐渐变窄归于无。

Unity中要想检测两物体的碰撞,必须都具有碰撞体,而且其中一方必须具有Rigidbody刚体组件;当时在实际应用过程中,因为刚体会消耗大量性能,在非必须的情况下要少用。这里敌人已经具有刚体组件,因此只需要为激光束添加Box Colider 2D碰撞器,当激光束和敌人发生碰撞时触发OnTriggerEnter2D方法,在这个方法里获取碰撞的敌人实例并调用它的TakeDamage方法即可实现激光束的伤害。

结算功能模块

玩家生命值为零或者成功通关后会弹出结算页面,结算页面会统计当前关卡玩家的击杀数,得分以及累计造成的伤害值,这些统计信息在游玩过程中由Player类中的变量统计存储。

系统实现

游戏的实现秉承能简化就简化能省就省的策略,玩家看不见的地方可以简单遮住,这样不仅能优化性能,也能降低开发成本,节省开发时间。下面从开发的五个模块详细叙述功能实现。

游戏入口功能模块实现

进入游戏

玩家打开游戏后进入主菜单,主菜单显示了游戏名,下面有进入游戏,设置,退出游戏三个按钮。点击后可以跳转到相应的场景,如下游戏入口界面。

点击开始游戏按钮后进入加载,此时画面上层的黑色遮罩会会淡入淡出,就像眨眼一样实现场景视觉上相对流畅的体验。当鼠标放在按钮上会有对应的动画效果,Unity的Animation动画采用关键帧的方式制作,对于一般的动画制作简单且流畅。如下游戏主界面按钮动画效果。

关卡选择模块实现

选择关卡

进入关卡选择页面后,可以看到没个关卡都具有动态效果,具体为每个关卡都是一个不断旋转的小行星,使用Shader Graph制作的全息投影效果,这样使得UI更具有科幻效果。每个关卡都有不同的风格背景,为了贴合他们的风格将小行星设置不同的颜色,如下关卡选择界面。

当鼠标停留在关卡UI上时,停留的UI会通过放大自身给予玩家反馈。因为这里的UI组件混合使用了模型和Unity UGUI组件,鼠标停留反馈用C#代码控制,如下关卡选择界面UI触碰效果。当点击具体关卡时,经过加载会跳转至关卡界面。

设置功能模块实现

设置界面可以通过主菜单或者游戏关卡中跳转,上面有5个设置分类,分别是视频,声音,控制,界面和其他,右下角又返回按钮,不同分类按钮的动画衔接非常流畅,如下设置界面。调整设置项主要有三种UI,下拉栏,滑动条和按钮组。

关卡功能模块实现

Demo演示

角色信息

进入关卡后可以看到,界面左下角是玩家所操控战机的血量和能量条,右下角是被动技能的充能条,当充满后会发射制导导弹,右上角是角色当前的分数。玩家战机初始位置在屏幕中下方,如下角色状态信息。

角色攻击

为了增加辨识度,玩家战机的主色调为蓝色,敌人的主色调为紫色。如下角色和敌人的子弹。

角色受击

当敌机收到攻击后会触发机体闪白效果,这样的收集反馈可以提高玩家的游戏体验。如下敌人受击闪白效果。

角色移动

可以看到角色战机正常移动,并且可以在键盘操作和鼠标操作间切换。

物品拾起

击杀敌人后可以看到会有道具掉落,并且在道具移动的过程中会有尾迹粒子特效,如下敌机掉落的道具。

护盾道具

游戏中设置了多种道具,分别为护盾道具,回复能量道具,回复血量道具,星星道具等。

玩家拾起护盾道具后,护盾缓慢展开并且散发蓝色光芒。如下护盾特效。

当护盾受到攻击时会有黄色高亮特效反馈,极具科幻风格。如下护盾受击反馈。

如下恢复能量道具拾起效果。

背景卷动

将背景Material的wrap mode调整为repeat,然后通过C#代码调整偏移值即可实现卷动效果。如下背景卷动效果。

自定义弹幕

通过调整子弹的发射方向可以实现非常炫酷的弹幕效果,当子弹的发射方向不断旋转,且旋转速度不断加快,会形成如下效果。如下炫酷的弹幕。

释放技能

在左下角能量值充满后,可以按鼠标中间触发主动技能持续性释放一道能量光束,处在光束中的敌人会不断受到伤害。能量值可以通过击杀敌人获取。如下玩家发射的能量束效果。

发射激光时,机体前方出现球形特效,然后向前方发射激光,其中混有电束和粒子束。

结算功能模块实现

玩家死亡或者通过关卡后会显示结算界面,结算页面包含分数、击杀数,造成的伤害数值,下方附有重玩和返回按钮以便玩家进行下一步的操作,如下结算界面。

结论

总结

本文介绍了基于Unity引擎的横版卷轴射击游戏的设计与制作,在设计与开发过程中,本文主要分析并且解决了如下问题:

第一,我分析了课题研究的背景以及国内外相关行业的发展情况,确定了选题的目标和研究意义。

第二,通过对游戏开发技术的学习,学习并使用各种设计模式,分析类似游戏的实现思路,加上自己的理解,选择适合本项目的技术。

第三,从玩家角度进行构思,分析作为玩家的需求,从对STG类型游戏的游玩过程中获得的经验和自己的理解,从功能性需求和非功能性需求完成了系统的需求分析。

第四,对系统进行总体规划设计,结合需求分析设计相应的基类,进一步分化出具有不同功能的子类,同时基于单例模式对一些全局性的功能进行实现,对具体的功能模块配以流程图描述具体的逻辑。这一步明确了要实现的具体功能。

第五,更具前面两步的分析和设计,利用相应的工具和技术制作游戏需要的美术资源,之后完成代码的编写,对各个功能模块的逻辑进行了详尽的描述。

第六,利用合适的测试方法,通过在合适测试环境下的测试结果对系统进行了完成度评估。

展望

项目开发历时3-4个月,基本实现了计划中的功能,可以满足玩家正常游玩。虽然在游戏的画面表现投入了较多时间使得画面的品质相对较高,但由于经验不足,制作的特效数量有限,系统依然存在一些不足,接下来会对游戏内容作进一步开发扩充,会在以下几个方面进行改进:

(1)部分UI效果仍需要优化:由于UI涉及到贴图,特效,shader,脚本的制作,需要花费大量时间,因此部分UI仍用的简单后处理和动画实现的,并没有达到我心里预期的那样。同时UI背景是静态的,下一步会优化UI表现,为背景增加一些动态效果。

(2)敌人种类单一:敌人种类单一,且没有独特的攻击模式,下一步会丰富敌机的行为,为敌人增加更多的攻击机制。

(3)道具效果单一:尽管实现了击中道具,但相对来说这些道具的作用比较常见,缺乏一些创新,之后会增加道具种类,以护盾的表现作为标准为道具添加炫酷的特效。

(4)设置页面可配置项较少:设置界面可配置的选项目前还比较少,无法达到一些玩家的需求,但考虑到本游戏对配置的要求较低,之后会再增加一些基础配置项而不会添加过多无意义的选项。

(5)玩家战机单一:玩家可以操控的战机单一,以及战机没有可配置属性,之后会添加战机各个属性升级,添加更多种类的战机。

正经总结

上面大部分内容都是毕业论文内容,内容比较详尽,所以我干脆搬到博客来了||ヽ( ̄▽ ̄)ノミ|Ю。

  • 标题: 基于Unity的3D飞行射击游戏-SpaceWarriors
  • 作者: 起风了
  • 创建于 : 2024-03-13 14:49:43
  • 更新于 : 2026-09-26 11:50:56
  • 链接: https://www.wangcac.me/2024/03/13/基于Unity的3D飞行射击游戏-SpaceWarriors/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论