杨淮敏,邱树伟
(韩山师范学院计算机与信息工程学院,潮州 521041)
游戏是一种以娱乐态度解决问题的活动,被称为第九艺术,好的游戏可以发人深省或让玩家放松心情、提升智力。目前,国产优秀的单机游戏屈指可数,究其原因,除了市场因素之外,游戏开发技术的复杂性也影响了国产单机游戏的开发。
文献[1]的研究指出,当下越来越多的游戏已经无法满足广大游戏爱好者的需求,玩家更倾向于玩法新颖、内存占用小、加载速度快的高品质游戏。游戏开发者必须快速高效地开发出成熟稳定的产品来满足玩家的需求。为了实现这一目的,Unity3D 引擎是首选的开发工具。文献[2]阐明Unity3D 是当前炙手可热的游戏引擎,由其设计的游戏能够在PC 端和手机端等多种平台间相互移植,并且有很全面的帮助文档和良好的用户交互界面,可满足开发者的需求。良好的可移植性与交互性使Unity3D 适合开发各类游戏。文献[3]通过结合Unity3D 游戏引擎组件与脚本、怪物智能导航及AssetBundle 加载技术等设计了一款角色扮演游戏。该游戏提供了打怪、升级、抽奖、商城等多种玩法和相关功能。文献[4]设计了一款冒险闯关游戏,通过集合不同的游戏类型使关卡难度层层递进。文献[5]通过结合碰撞体与刚体设计了对游戏人物进行基本操控的方法。文献[6]设计了一个脚本语言与解释器,实现了一系列的AI 及关卡逻辑功能。文献[7]介绍了键盘交互技术与碰撞检测技术,给出了游戏开发项目流程。
从以上成果可以看出,目前,在基于Unity3D的游戏设计与开发方面已取得一些成果。然而,上述成果还可以进一步完善,具体如下:①在系统设计方面,可以设计多个低耦合的子系统,使得游戏的功能更为完善与全面;②在系统实现方面,可以进一步完善战斗系统、增加关卡系统以及装备系统等,以改善游戏体验。
本文旨在基于Unity3D 引擎技术,配合DOTween 插件和C#脚本语言,开发一套单机冒险游戏,实现游戏通用的基础功能模块,通过这些功能模块展示一个游戏软件的基本框架,主要功能模块包括:游戏存档、限制玩家游戏时间、选择关卡、战斗、商店、英雄信息展示等。通过该游戏的设计与实现,与广大游戏开发者分享相关技术和方法,帮助开发者减少开发成本,简化开发流程,使开发者能够专注于设计自己独有的游戏规则,实现具有特色的游戏功能。
Unity 引擎具有极高的灵活性,开发者可以为多个平台开发游戏,如IoS、安卓、Windows等。Unity 引擎还提供了诸多服务,如内容发布平台,Unity Asset Store(UAS)等,其中,UAS的插件、素材、开发者社区、用户手册等都可以很好地帮助开发者开发游戏。此外,运行Unity脚本会按预定顺序执行事件函数,在脚本的生命周期内事件函数的执行顺序会对游戏效果产生影响。
DOTween 插件是一个类型安全的免费开源面向对象动画引擎,还有大量高级特性,将它导入Unity 中可以快速地完成许多动画效果。这款插件可以使开发人员快速地进行各类动画的设计和创作,能够有效提升游戏开发的效率。DOTween 插件允许通过代码以简单的方式制作流畅美观的动画。使用DOTween 插件实现的动画效果与补间动画相似,它不仅可以用于UI上,还可以用于物体的移动等。
Unity脚本主要使用C#语言。C#是一个简单的、通用的、面向对象的编程语言,能够产生高效率的程序,可以在多种计算机平台上编译。C#的跨平台特性可以解决Unity引擎的跨平台支持问题。实际上,跨平台的是C#编译后所生成的中间语言(CIL)。
由于本游戏是一款单机冒险游戏,因此,其功能模块的实现比较重要,游戏功能结构如图1所示。具体功能需求如下:
图1 游戏功能结构
(1)游戏存档:包含开始新游戏、继续游戏和退出游戏。玩家无需注册就可以进行游戏,开始新游戏时此前的游戏数据会消失,需要谨慎对待,因此会有再次确认的提示。
(2)限制游戏时间:限制游戏时间为1 小时/天,当剩余游戏时间为10分钟时,计时器颜色会变为红色以便提醒玩家,超出时间会弹出警告面板并且无法进行游戏。
(3)选择关卡:包含解锁关卡、更新通关星星数、解锁章节。在一个章节中,关卡一默认解锁,玩家通过关卡一后会自动解锁关卡二,同时记录关卡一获得的星星数。如果关卡一未通关则不解锁关卡二,当所有关卡满星通关后会解锁下一章节的关卡。
(4)商店功能:可以购买武器、英雄,购买成功与否均有反馈。玩家购买武器时成功与否都会有提示。购买英雄成功则会有动画播放,动画播放完后刷新商店,不允许再次购买该英雄。
(5)英雄展示:展示已购买的英雄信息,可以升级英雄并装备武器,同时,可以选择是否让英雄加入战斗队列。玩家可以通过左右两个按钮切换想要查看信息的英雄,可以选择英雄出战或休战。升级英雄需要金币和经验,点击装备槽可以展示装备信息或者进行装备,技能也可以升级。
(6)战斗功能:设计英雄和敌人基类,实现敌人AI,可以切换英雄进行战斗,同时设计远程攻击与普通攻击的实现类,通关成功与否均有反馈。
在玩家开始游戏时会首先进入登录界面,玩家可以选择继续游戏(读取之前保存的游戏数据)或开始新游戏,进入游戏后会开始计时,如果累计游戏时长到达一小时,会出现提示界面并无法继续游戏,否则每过一分钟都会更新一次游戏时长的数据并进行游戏时长的判断。开始游戏流程如图2所示。
图2 开始游戏流程
在进入战斗场景后,系统会检测玩家是否按下了切换键,按下切换键就会使用队列的下一个英雄进行战斗,当前英雄死亡也会切换为下一个英雄继续战斗,如果英雄队列中的英雄全部死亡则游戏失败;同时每次英雄受伤与攻击都会播放相应动画,每次英雄受伤时会判断该英雄是否死亡;敌人如果受伤会播放受伤动画并判断是否死亡,如果死亡就播放敌人死亡动画并判断是否战斗场景中的敌人全部死亡,如果全部死亡则游戏胜利;敌人会在游戏场景进行巡逻,如果英雄走到敌人的攻击范围,敌人会进行攻击与追击。战斗流程如图3所示。
图3 战斗流程
本系统实现了游戏的关卡子系统、商店子系统、背包子系统、英雄信息展示子系统、战斗子系统以及存储子系统等,各子系统所采用的素材引用自文献[8]。
本子系统实现的功能包括:跳转场景、章节选择、关卡选择等。系统实现的主要功能如下:①跳转场景:通过使用场景类SceneManagement 的LoadScene()方法获取场景名进行跳转。②章节选择:运行时通过本地持久化类PlayerPrefs 获取数据判断章节是否解锁,若解锁则按钮允许交互,实现界面如图4所示。③关卡选择:每次加载关卡选择界面时通过获取数据更新显示当前关卡星星总数,上一关卡解锁则下一关卡可以进行挑战,其他关卡仍无法挑战。读取出战英雄队列,若为空则遮挡住关卡选择界面使玩家无法进行挑战,当关卡星星数等于总数时解锁下一章,实现界面如图5所示。
图4 章节选择界面
图5 关卡选择界面
本子系统实现的功能包括:商店面板切换、英雄购买、购买成功动画、武器购买等。系统实现的主要功能如下:①商店面板切换:通过使用Transform.SetSiblingIndex()方法改变面板在Hierarchy层次上的顺序,从而实现面板的切换。②英雄购买:通过CanvasGroup 组件控制透明度,实现点击购买按钮时打开确认购买界面,通过读取ScriptObject 保存的数据展示已设置好的英雄信息与人物图,实现界面如图6 所示。③购买成功动画:通过使用DOTween 插件里的联合动画Sequence 的Append()方法实现UI动画的设置,实现界面如图7所示。
图6 英雄购买界面
图7 购买成功界面
本子系统实现的功能包括:物品槽生成、物品槽更新和物品信息展示等功能,实现界面如图8 所示。系统实现的主要功能如下:①物品槽生成:手动创建一个Prefab 预制体后,通过创建列表List 存储实例化的预制体,从而实现多个物品槽的制作。②物品槽更新:打开背包界面时会对物品槽的信息进行更新,通过ScriptObject 获取玩家存储的物品数据,在物品槽中展示物品图片与数量。③物品信息展示:点击物品槽时显示物品信息及出售按钮,出售数量为1 时不许减少出售数量,未拥有物品数时不许增加。
图8 背包系统界面
本子系统实现的功能包括:选择更换出战英雄、展示出战英雄、升级英雄与武器、给英雄装备武器等。系统实现的主要功能如下:①选择更换出战英雄:通过True 和False 设置英雄的出战状态,出战队列已满时无法增加出战英雄,通过英雄图像下方的按钮实现选择英雄或者替换英雄后,出战队列的英雄头像会进行更新,如图9 所示。②升级英雄与武器:通过简单的条件判断实现英雄与装备的升级,升级将会带来属性数值的提升。③给英雄装备武器:给英雄装备武器时需要从玩家背包查找多余的武器,装备成功则背包武器少一件,同时武器属性与角色职业挂钩,如剑士不可装备魔法书,实现界面如图10所示。
图9 英雄出战界面
图10 英雄装备界面
本子系统实现的功能包括:敌人AI、玩家角色控制、切换战斗角色、普通攻击与远程攻击、游戏胜利与失败等。系统实现的主要功能如下:①敌人AI:在进入战斗场景时初始化敌人的血条同时更新敌人信息,如果玩家切换了战斗英雄,攻击目标也会转换为玩家当前使用的英雄。当英雄进入攻击范围时会进行攻击并进行追击,否则敌人会在两点间进行巡逻。当敌人受伤时生命值减少,播放受伤动画,死亡时播放死亡动画并销毁自身,如图11 所示。②玩家角色控制:设置英雄可以进行二段跳、移动、下蹲、攻击、起立等行为,同时使用射线检测英雄的左右脚是否在地面上以判断是否可以进行二段跳。③切换战斗角色:按下F 键时可以切换英雄进行战斗,此时会更新当前英雄信息,同时摄像机会跟随当前英雄,血条信息和出战英雄面板信息也会得到更新。④普通攻击与远程攻击:根据英雄的职业分别设置普通攻击和远程攻击。普通攻击的原理是勾选碰撞体的isTrriger属性,在碰撞敌人的时候触发伤害。远程攻击创建了已设置好的预制体进行水平运动攻击敌人,运动到一定距离即自我销毁。⑤游戏胜利与失败:当玩家的所有英雄都被击败时会暂停游戏,显示游戏失败面板;玩家击败场景中的所有敌人时会暂停游戏,显示游戏胜利面板,同时根据死亡英雄的数量来判断以几颗星通过本关卡,在胜利面板会显示英雄信息,显示通关获得的经验和金币,如图12所示。
图11 战斗界面
图12 战斗胜利界面
存储子系统的实现主要采用PlayerPrefs。PlayerPrefs是一个用于数据本地持久化保存与读取的类,它将数据以键值对的形式保存在本地,使用它能够轻松实现数据存储,在本系统中使用PlayerPrefs存储了关卡星星数等。
由于ScrtptObject 的特性是在编辑模式或运行模式下修改的数据在游戏退出后不会保存,故开始新游戏只需要删除已保存的PlayerPrefs键值对。继续游戏相对复杂,在保存游戏数据时需要使用Json 将ScriptObject 序列化转换为String 类型,再将String 类型保存在PlayerPrefs键值对中,读取数据则需要读取键值对的String,最后将其反序列化为ScriptObject。
本文基于Unity 游戏引擎设计和实现了一款单机冒险游戏,该游戏无需设计复杂的算法,采用C#脚本语言实现,代码只需要逻辑清晰即可实现。本游戏开发过程中注重提高代码的复用性以及降低模块间的耦合性,节省了开发成本。本文具体做了以下工作:
(1)在游戏实现方面,主要实现了关卡子系统、商店子系统、背包子系统、英雄信息展示子系统、战斗子系统、存储子系统等,完成了游戏的基础功能模块。
(2)在素材制作方面,通过绑定骨骼,制作了多个英雄的多个骨骼动画,通过对英雄行为动画进行精细的调整,实现了良好的动画效果,同时使用序列帧制作了敌人的各种行为动画。
(3)在界面设计方面,积极寻找优秀的界面设计提升审美,最终实现了良好的界面设计,同时还增加了部分UI动画。
本游戏的设计和实现对于基于Unity 游戏引擎的单机版游戏开发具有积极的借鉴作用。