基于Unity3D的AVG卡牌游戏设计与实现

目 录

摘 要 I
Abstract II
引 言 1
1 相关技术 3
1.1 C# 3
1.2 Unity3D 3
1.3 UGUI 3
1.4 XML 4
1.5 原型设计模式 4
1.6 本章小结 4
2 系统分析 5
2.1 用户需求 5
2.2 功能需求 5
2.3 非功能需求 6
2.4 本章小结 6
3 系统设计 7
3.1 系统该要设计 7
3.2 系统详细设计 7
3.2.2 数据逻辑结构设计 10
3.4 UI设计原则 11
3.5 本章小结 12
4 系统实现 13
4.1 开发环境 13
4.2 开发规范 13
4.3 数据存储和读取实现 13
4.4 核心功能实现 14
4.5 本章小结 16
5 系统测试 17
5.1 测试计划 17
5.2 游戏测试 17
5.4 本章小结 17
结 论 19
致 谢 20
参考文献 21

摘 要

21世纪随着社会飞速进步和科技的发展,对于工作和学习压力越来越大,对于缓解压力的需求逐渐增多,但是大多数人的时间碎片化,需要简单,快速的活动来放松身心,这就使得游戏开发被人们所需要。基于社会需求,本项目针对休闲新颖的玩法开发了一款AVG卡牌游戏。
通过对市场需求的分析以及行业现状的调研。本项目运用了Unity引擎进行游戏开发,采用轻量级UI消息框架,用于UI之间的通信,解决了一对多的通信问题。使用管理器设计模式+原型设计模式,使游戏代码和数据更加干净整洁,更易于控制和管理。使用了XML可标记语言进行数据的读取和存储,该语言特点是方便快捷的快速使用。使用可UGUI进行游戏页面的搭建和游戏数据的可视化显示,UGUI是目前Unity引擎主流的UI组件,组件自身功能较为成熟,不需要过多的考虑功能的设计,能够满足大部分显示的需求
本项目经过测试后,基本实现预期功能,能够体现完整的游戏性,展现了AVG的特点,添加了Roguelike元素以后,游戏不会因为重复体验而带来枯燥的感觉。项目本身采用的框架设计模式,后续继续开发拓展新功能的难度大大降低。

关键词:AVG卡牌; Unity3D引擎; Roguelike

Abstract

In the 21st century, with the rapid progress of society and the development of science and technology, the pressure on work and study is increasing, and the demand for relieving the pressure is increasing. However, most people’s time is fragmented, and they need simple and rapid activities to relax their body and mind. Therefore, game development is needed by people.
Based on social needs, this project develops an AVG card game for leisure and novel gameplay.Through the analysis of market demand and the investigation of the current situation of the industry.This project USES Unity engine for game development, and USES a lightweight UI message framework for communication between uis to solve the one-to-many communication problem.Use the manager design mode + prototype design mode to make the game code and data cleaner and easier to control and manage.XML markup language is used for data reading and storage, which is characterized by convenient and quick use.UGUI can be used to build game pages and visually display game data. UGUI is the mainstream UI component of Unity engine at present, and its functions are relatively mature, so it does not need to consider the lack of functions too much, and it can meet most display requirements
After the test of this project, the expected functions are basically realized, which can reflect the complete gameplay. The features of AVG are shown and the Roguelike element is added, so that the game will not bring a boring feeling due to repeated experience.The framework and design patterns adopted by the project itself make it much easier to continue developing and extending new features.nd can meet the learning and communication needs of most users.

Keywords: AVG Card; Unity; Roguelike

引 言

现在市面上的游戏类型种类繁多,玩家的喜好的游戏类型不尽相同,重口难调。卡牌游戏是一个总能被人们津津乐道的游戏类型,因为卡牌游戏本身是一个需要经过思考过程的博弈过程,不需要高强度的操作就能完成。这也满足了休闲游戏的特点。
为了满足休闲游戏的特点,让游戏能够轻松进行,并且不枯燥的重复进行,需要有足够游戏环节进行支持,卡牌游戏的思考过程,以及AVG[1]冒险性的体验感,同时还添加了Roguelike的元素[2],保证了游戏的特点,并将其升华。本项目的核心系统主要分为以下几个部分:
角色模块:角色模块是游戏的基础,玩家在进入游戏的时候,会选择一名角色,从而获得这个角色的基础卡组,每个角色对应的基础卡组和后续收集到的卡牌都不会相同,每种角色的核心玩法都不会相同,能够给玩家带来不同的体验
卡牌模块:卡牌游戏为游戏的主要核心部分,每张卡牌会有自己特点,卡牌会有各类的属性数值,玩家在游戏过程中会获取不同的卡牌,来组成自己的卡组,卡组中的卡牌是玩家在冒险过程中的主要手段,充分利用这些卡牌为自己的战斗中获取优势,从而最终赢得胜利。
地图模块:地图模块是体现Roguelike元素的主要体现,玩家在选择完角色之后,会获取一张地图,这份地图中会有各种图标,每种图标代表的是一个类型的房间。因为路线的不可后退性,玩家应当思考需要行进的路线来决定该进入哪个房间,这会影响到后续的游戏。
战斗模块:本游戏的战斗采用的回合制战斗,在进入了可以战斗的房间以后,玩家会和敌人遭遇,不同的敌人的行动规则不同,会在敌人的角色上方进行提示,玩家在回合开始会有相应的行动点,行动点有限,行动点所对应的是卡牌上的消耗。玩家应该根据提示来决定这一回合需要打出的卡牌,同时玩家应该在这其中思考如何在下一回合开始时能获取优势。在战斗过程中,某一方先死亡,结束战斗。在玩家取得这一场
房间模块:在整个地图中,会存在不同的房间,不同的房间,玩家所经历的事件也不会相同,在战斗房间,玩家和敌人遭遇,展开战斗。在商店房间,玩家可以购买,相应的卡牌和使用移除卡牌服务。在宝箱房间,玩家可以直接获取奖励,提升自身。在休息处,玩家可以选择回复生命值或者提升卡牌的品质增加战斗力。
本文的总体结构为第1章相关技术综述,该部分用于介绍游戏开发所使用的框架,以及游戏开发所使用到的相关技术等;第2章游戏系统分析,该部分将对游戏内容的需求进行具体的详细分析,策划其游戏目标、研究其可行性以及游戏的需求分析工作;第3章系统设计,从总体上确定游戏的设计方案、组成游戏系统的模块以及模块之间的关系。同时要进行本地数据存储设计、以及确定每个模块应该如何被详细实现,包括游戏过程设计;第4章系统实现,阐述游戏的具体实现过程,按照顺序演示核心功能的核心代码,并对其进行解释说明;第5章游戏测试,该部分将介绍完成项目功能实现后如何开展测试工作的测试计划、测试用例,性能测试等。

1 相关技术

本项目采用C#作为开发语言。使用了Unity引擎作为游戏开发引擎[3]。UI搭建和显示使用了UGUI。数据读取和存储使用了可标记XML语言。代码架构使用了管理器设计模式[4]和原型设计模式[5]。
1.1 C#
C#作为微软公司推出的一种面向对象的语言与JAVA相似,运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言[6]。
C#是微软公司研究院的新的成果,是由C和C++衍生出来的面向对象的编程语言,在继承C和C++强大的功能的同时也去除了他们复杂且多重继承的特性[7],C#与开发环境很完善,功能齐全,并且支持匿名类,匿名委托,泛型的特点,可以极大的提高程序员的开发效率和提升逻辑的清晰度[8],使得C#成为当今世界变成语言的不可或缺的一部分。
1.2 Unity3D
Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎[9]。
Unity在2009年,注册人数已经高达3.5万人,2010年开始支持Android,继续扩张影响力。2011年有陆续支持PSP等掌上电子产品,2013支持IOS,跨平台能力很难让人挑剔,一套代码只需要换相应的开发API,做支持,SDK介入就可移植手机端,现在更是涉猎与VR,AR,虚拟仿真等领域并取得了不错的成就[10]。缺点在于其渲染能力相对于UE4而言,稍微逊色一些。Unity是目前全球最普遍的游戏引擎[11],能够创建实时、可视化的2D和3D动画、 游戏,被誉为3D手游的传奇,孕育了成千上万款高质、超酷炫的神作:《炉石传说》《神庙逃亡2》《我叫MT2》。
1.3 UGUI
UGUI系统是从Unity 4.6开始,被集成到Unity的编辑器中Unity官方给这个新的UI系统赋予的标签是:灵活,快速和可视化[12]!简单来说对于开发者而言就是有四个优点:效率高效果好,易于使用,扩展,以及与Unity的兼容性高[13]。
在不使用任何代码的前提下,就可以简单快速在游戏中建立其一套UI界面,这在过去是绝对不可想的,但是新的UI系统确实做到了这一点因为Unity预定义了很多常见的组件,它们以“游戏对象”的形式存在于游戏场景中。
1.4 XML
可扩展标记语言(eXtensibleMarkup Language,简称XML),是一种标记语言[14]。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性[15]。
1.5 原型设计模式
原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象[16]。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
1.6 本章小结
以上介绍的技术均为本项目所使用的技术,包括Unity3D引擎,UGUI,XML,原型设计模式,管理器设计模式。从游戏页面显示到数据存储,都有详细描述。本章对于游戏开发所使用到的技术,都有了详细描述。

2 系统分析

系统分析主要分为2个部分,功能需求和非功能需求。本项目主要的模块有:人物角色模块,战斗模块,游戏房间模块,卡牌模块,UI搭建模块,场景搭建,地图模块。
2.1 用户需求
在日常工作和学习之余,总会需要放松身心,休闲益智类游戏带给人们简单轻松的快乐。卡牌游戏是休闲游戏的代表之一,其中有相当多的博弈过程,取代了高强度的操作,只需要点击就可以带来互动性[17]。AVG冒险题材,玩家会扮演一个角色,从角色自身触发带入到游戏当中,去经历游戏世界里发生的种种。但是卡牌游戏的重复性是一个致命的缺点,所以如果能有一些随机的元素添加到AVG卡牌中,这会使得这一游戏变幻莫测,给人带来特别的体验。
2.2 功能需求
根据用户的需求分析出游戏包含的系统,主要的模块有:人物角色模块,战斗模块,游戏房间模块,卡牌模块,UI搭建模块,场景搭建,地图模块。
主菜单UI模块:进入游戏后需要有相应的主菜单,主菜单需要有基本的游戏风格,展示游戏的标题,可操作的游戏界面,在菜单上的文字可以展示相应的功能,点击之后有相应的展示。可以适当装饰主菜单。
人物角色模块:人物角色模块应当展示相应的人物信息,有提供给玩家选择的角色,给角色添加相应的说明,可以返回主菜单的按钮以及进入游戏的按钮。角色模块需要有相应数据支持,每个角色会对应不同的卡牌[3]。
卡牌模块:每个玩家在选择完角色之后会获得一定数量的基础卡牌,卡牌上会有相应的说明,基础卡牌分为三种类型,分别是攻击类卡牌、技能类卡牌、能力类卡牌,每种卡牌会有不同的品质,卡牌上能显示对应的功能和消耗。
地图模块:在选择完角色后,给玩家提供地图使玩家能够进行游戏,每种地图图标对应了不同的房间类型,只有同一层的房间能够提供给玩家点击。
战斗模块:玩家进图地图后,会出现在游戏场景中,玩家在左边,敌人在右边,战斗开始后,给玩家发规定数量的卡片,玩家应当应当根据怪物行动提示和自己的体力消耗来决定打出的卡牌。直到一方没有剩余的生命值,这场游戏结束。
UI模块:在游戏的上方,会提示游戏玩家名称、使用角色的名称,当前血量和最大血量,可以查看地图,可以查看自己所有拥有的卡牌,可以打开系统设置面板。
场景模块:使用提前准备好的图片素材,对这些图片素材进行拼接,拼接完成之后,添加相应的光照和相机特效。
2.3 非功能需求
游戏流程基本完善,响应时间符合预期,游戏能够在多数设备上流畅运行即可。
2.4 本章小结
本章介绍了需求设计, 确认了整个游戏的核心玩法,通过游戏风格和玩法特色提出了游戏本身应该具备的系统及功能。

3 系统设计

系统设计可分为概要设计和详细设计两个阶段。系统的概要设计主要是从总体上确定系统的设计方案、组成系统的模块以及模块之间的关系,同时进行数据设计、实现计划和测试计划。详细设计的主要目的是确定每个系统应该如何被详细实现,包括游戏过程设计等等。
3.1 系统该要设计
对于整个游戏而言,需要一个整体框架,本项目所使用到的整体框架为管理+数据包设计模式,类比MVC设计模式[18]。在游戏中MVC设计模式并不能广泛用于整个游戏,在使用过程会显得十分生硬。本项目所使用到的设计模式参考PureMVC框架[19]。游戏系统之间会存在单独的管理器,管理这一类别的对象。
3.2 系统详细设计
玩家在进入游戏后如图3.1所示
在这里插入图片描述

图3.1玩家开始游戏
在开始游戏后,玩家会先选择角色,选择角色时,展示角色相应的生命值,金钱和说明,在选择完角色后,进入第一个场景与NPC对话,选择合适的Buff开始进行游戏,可以查看生成的地图。
在选择路线时如图3.2所示
在这里插入图片描述

图3.2玩家选择路线
玩家根据地图展示的路线选择合适的房间进入,会显示相应的敌人,敌人会显示数量和种类,提示玩家这一回合的行动模式,玩家会被战斗系统从手中已有的卡牌中获取一定数量的卡牌。玩家需要根据怪物的行动模式和手中已有的卡牌以及行动点来决定打出的卡牌,卡牌在打出后生效并影响敌人。在玩家点击回合结束后,战斗系统回收玩家手中剩余卡牌,轮到敌人行动。在敌人的行动结束后,这一回合结束,玩家回复行动点,重新在玩家的卡组中抽取卡牌,当抽卡组中没有卡牌时,会从弃牌组中重新获取所有卡牌,并进行洗牌。
玩家在进入商店时候如图3.3

在这里插入图片描述
图3.3玩家进入商店
玩家在进入商店后,可以通过战斗获得的金钱来购买卡牌提升自己,也可以从商店中移除不需要的卡牌。
玩家在进入休息处的时如图3.4
在这里插入图片描述

图3.4玩家进入休息处
玩家在进入休息处时可以在休息处休息恢复血量,或者选择锻造升级一张卡牌,在点击升级卡牌时,升级系统会展示相应的升级后的数据来提供给玩家参考。
3.2.2 数据逻辑结构设计
游戏角色基本信息,这是玩家选择一个角色后所要展示的信息,包括角色名称、初始金币、角色描述、角色类型、最大血量和当前血量。
表3.1角色信息表
字段名 数据类型 描述
Name String 角色名
Coin Int 角色金币
Description String 角色描述
Type Enum 角色类型
MaxHp String 最大血量
卡牌的基本信息,每张卡牌都有自己的信息,这些信息用于描述这张卡牌的用途,卡牌的地图用于显示卡牌的图片,卡牌路径用于加载卡牌图片的路径。卡牌ID代表这一卡牌自身索引。卡牌花费用于在一回合行动中所要花费的行动点数。卡牌名是卡牌记的中文名称。对应的游戏对象是卡牌数据在被加载。目标类型是判断使用的目标种类。初始卡牌数值是卡牌未升级时所要展示的数值。当前使用数据是记录卡牌被使用时产生的数值。升级卡牌的数值是指,升级过后的数值。卡牌是否升级是标注卡牌是否被升级过。卡片描述用于解释说明卡牌的用于以及特性。使用者是表明卡牌使用过程中是谁在使用卡牌。卡牌特性描述是在使用卡牌时,对于特性的描述。卡牌类型是这区别卡牌的3种类型之一有三种,分别是:。卡牌的基础攻击是当前卡牌的攻击数值。卡牌价格是在商店中出售卡牌时的价格。
表3.2 卡牌表
字段名 数据类型 描述
ImageIndex int 卡片底图
ImagePath string 卡片路径
ID int ID
Cost int 卡牌耗费
Name string 卡牌名
GO object 对应游戏对象
TargetType enum 使用目标类型
InitValue List 初始卡牌数值
CurrentValue List 当前使用数值
UpgradeValue List 升级卡牌数值
Upgraded bool 卡牌是否升级

表3.3 敌人表
字段名 数据类型 描述
ID int 怪物ID
Name string 怪物名字
MaxHealth int 怪物血量
Health int 当前血量
BaseAttack int 怪物基础攻击
DialogOffset string 对话框偏移
PrefabPath string 怪物路径
Single bool 能否能单独出现
MonsterType enum 怪物类型
BehaviourDescription List 行为描述
BehaviourSequence object[] 行为队列
BehaviourDialog List 行为语言

3.4 UI设计原则
(1)类需要与机器交互,所以交互有关界面设计都是UI设计,仅游戏而言,玩家的上手快慢与游戏UI设计有直接的关系,UI设计就非常好,玩家可以快速简单高效的进行游戏,不会因为操作过于繁琐而忘记,同时提供一目了然的选项,让玩家直观的去操作,是非常重要的。
(2)一个UI的好坏更加注重的是可扩展性,游戏是需要迭代更新的,没有一个合理的框架来进行管理为拓展提供条件是一颗非常不可取的行为[20],当UI发生改变,其功能发生变化,不适用框架,会造成棘手的现象,甚至之能推翻重做。这样非常不便于更新,对于如今对数据更新换代告诉发展的趋势而言,没有框架作为对扩展的支持,它并不能被快节奏的现代生活所接受[21]。
(3) UI功能的稳定性,在UI结构布局确定以后,必须对整体架构保持稳定,高效才可进行具体开发 ,开心厨房这款游戏,菜单的读取没有一个好的菜单排列,并顺序读取内容,是非常糟糕的,所以UI需要跟据数据来展示不同的内容。
(4)UI的可复用性。这便是框架的作用,既可以节省开发成本,还能提高自身工作效率,良好的可复用性是一个合格系统所用应具有的性质之一[22]。
3.5 本章小结
本章介绍系统的设计和数据的设计,在设计系统的时候会根据系统的功能而考虑适当的设计模式配合,数据逻辑设计主要配合功能实现的设计,为系统设计提供足够的数据支持。

4 系统实现

本系统在window10操作系统,运用Unity引擎进行开发,运用简单易于读取的json作为数据支持,通过C#语言完成整个游戏,游戏整体。本系统特点在于游戏性,以及复杂的功能逻辑。
4.1 开发环境
本系统使用了Windows 10 企业版 64-bit操作系统,该操作系统为目前主流操作系统,界面简约好看,操作不复杂,操作环境好。本系统开发环境为CPU即Intel® Core™ i5-6300HQ CPU @ 2.30GHz,内存为8GB,硬盘即256G SSD,开发引擎为Unity3D2017.4.20f2;本项目的代码编写工具为Visual Studio2019。
4.2 开发规范
代码的规范性和一致性使团队协作开发速度得到了提升,同时也提高开发者对代码理解的清晰程度和改修代码的难易程度。代码的程序结构以及命名风格是开发系统时的重要环节,决定一个项目是否成立的关键一步[23]。命名方法为大驼峰。方法命名为大驼峰,例如ExampleMethod()。脚本变量和属性命名方法为小驼峰,例如myVariable。
4.3 数据存储和读取实现
XML可标记语言来进行数据的存储,利用System.XML进行数据的操作。根据指定路径加载到内存中。通过API加载所有XML文件信息,遍历节点获取数据,并分类保存[24]。
XML存储数据主要通过文本的形式,树型结构。在根节点下可以延伸子节点,在子节点中,存储子节点的属性。子节点可以嵌套子节点,卡牌特性数据,如属性ID,属性名,页面呈现时颜色,属性描述等,XML结果如下展示所示:

<?xml version="1.0" encoding="utf-8" ?> 卡牌特性加载过程,获取到XML文件路径,声明一个存储数据的容器,声明一个XML文件对象实例,声明XML读取规则对象实例,更具规则实例读取XML文件对象。从节点和属性中获取需要保存的数据并存储。 展示: /// 4.4 核心功能实现 如图4.1所示为游戏主菜单界面,主菜单显示了游戏的标题,标题后有可以重复滚动云做装饰。这一场景是作为游戏的初始场景,界面如图4.1所示。该功能的核心功能如下所示,详细参考附录1主菜单实现类。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1858b367dfcd4174b32a4ae543cfe8da.png)

图4.1 游戏主菜单界面
界面设计主要利用了Unity3D引擎的UGUI,背景中的云彩使用了重置RectTransf的锚点位置,利用锚点的重置,达到了一个循环的效果,主要组件有Text组件,Image组件和Button组件,在这些组件中添加相应的回调方法,来实现每个组件的具体功能。而UI在很对时候是一个多对一的关系,所以在需要有多个回调的时候,可以给这个组件添加关心事件,利用关心事件,来实现多对一,本质参考了观察者设计模式的思想,详细参考附录1主菜单实现类。
战斗页面所涉及到的模块较多,最上方的是UI模块,下方是抽卡堆,当前手牌,洗牌堆,中间左边的为玩家角色,右边为敌人角色,两个角色下方显示的是双方的生命值。
如图4.2所示为战斗界面,核心代码参考附录2战斗回合管理类。
在这里插入图片描述

图4.2 战斗模块界面
在进入战斗时,玩家先开始,玩家会从玩家所有卡牌中克隆出一份新的卡组,然后添加到抽卡堆当中,在抽卡堆中随机抽取相应数量的卡牌,添加到玩家持卡卡组中,也就是图片正中区域展示的卡牌,玩家点选卡牌以后,会出现一个箭头,这个箭头是使用了二阶贝塞尔曲线完成的UI。箭头所指的对象,就是卡牌的使用对象,在箭头变为红色以后,就可以使用卡牌。玩家使用卡牌后会实现卡牌相应的效果,并从可行动点中扣除行动点,然后将使用后的卡牌添加到右下角的弃牌堆当中。玩家点击结束会后,回合就转到敌人,敌人会按AI的预先行动和回合数决定这一回合要做什么。在敌人的回合结束以后,就会重新开始一个新的回合。
如图4.3为商店界面,在商店中随机出售部分卡牌,并有特价卡牌,右下角为卡牌移除服务可移除卡牌,核心代码如下:
在这里插入图片描述

图4.3 商店模块界面
for (int i = 0; i < CardPoints.childCount; i++)
{
AllCardPoint.Add(CardPoints.GetChild(i).GetComponent());
}
for (int i = 0; i < RelicsPoints.childCount; i++)
{
AllRelicsPoint.Add(RelicsPoints.GetChild(i).GetComponent());
}SetPointEnter(RemovePoint.transform.Find(“Card”).GetComponent(), OnCardRemoveEnter);SetPointExit(RemovePoint.transform.Find(“Card”).GetComponent(), OnCardRemoveExit);
SetOnClick(RemovePoint.transform.Find(“Card”).GetComponent(), OnCardRemoveClick);

4.5 本章小结
本章主要详细介绍了项目开发阶段的开发环境及编码规范,并列展示了部分核心功能界面,项目的基础功能的实现到这里基本结束。接下来开始对项目进行测试。

5 系统测试

游戏开发完成后,对整个游戏的玩法以及整体功能进行了测试,在测试过程中没通过表现对游戏源码进行断点调试以及Debug处理,根据各个功能模块做了详细的测试。
5.1 测试计划
针对整个项目的每一个模块进行测试,在开发过程中,语法错误会被代码编辑器提示,逻辑错误则需要在Unity引擎中进行测试,在Unity的控制台中会提示当前错误的原因,已经脚本运行错误位置,这时就可以根据错误的位置及时进行修改,而还有部分测试会在游戏运行中,没有被Unity引擎所发现的[25]。这类错误就需要人为的手动调试,应当对游戏的功能进行了详细的测试,以真实反映游戏的功能。
5.2 游戏测试
表5.1游戏测试表
测试项目 测试目的 测试结果
打开游戏 游戏是否能够顺利加载 正常打开
开始界面功能 主菜单界面功能是否完整 可以顺利进入和退出游戏
选择角色进入游戏 选择角色进入游戏后游戏初始化是否顺利 玩家正常进入游戏游戏初始化正常
选择房间进入战斗 地图生成无误 玩家能够顺利进入地图房间
测试项目 测试目的 测试结果
玩家卡牌和敌人交互 战斗流程是否完整 战斗流程完整,buff属性添加顺利,敌人死亡后顺利进入地图
商店房间 是否能进入商店,并使用商店功能 可以进入商店并使用商店的购买服务和移除卡牌服务
奖励房间 是否能进入奖励,并获得奖励 可以进入奖励房间,并获得奖励
休息房间 是否能进入休息房间,并使用休息房间功能 可以进入休息房间,可以在休息房间获得升级卡牌或回复生命
测试项目 测试目的 测试结果
5.4 本章小结
本章主要叙述了本系统在检查调试过程中需要完成的工作,主要是介绍该管理系统的测试方法以及需要提前做的准备工作、还有在测试过程中的测试条件以及测试最后所达到的效果,经过系统检查调试使系统更适合用户的需求,更加稳定可靠地运行。

结 论

通过对Unity游戏引擎脚本编程的了解,完成了对整体游戏的一个设计,想要做一个游戏确实具有很大的挑战,不仅仅是功能实现带来的苦恼,必须要有一颗清醒的头脑去思考出相应的步骤,才可顺利进行下去,这使得整体开发没有想象中的那么顺畅,前期策划以及对整体游戏的思考还需要更加细致的去商讨并进行再三修订,才能在后续写代码,对整体游戏更加明确,提升开发速度。
游戏开发不同于软件设计,游戏开发并没有一个整体的框架概念,因为游戏的灵活性,很多时候生搬硬套一套框架反而得不偿失,被框架所束缚住。所以在开发过程中需要灵活应变,条条大路通罗马,也需要筛选,在有限的条件下筛选出和项目最为贴合的框架。设计模式就显得格外重要,大大小小的框架都建立于设计模式上,设计模式和数据结构在游戏整体框架当中显得格外重要,这也会是一个积累的过程。
本人在此次毕设结束后,将继续开发该项目,在后续开发当中,会添加其他游戏元素,而对于项目本身而言,需要优化的地方还有很多,游戏数据可以更改为使用Excel表格的形式,利用JSON的形式存储在本地,表格的配置更为便捷,JSON的读取效率更好,在战斗AI方面可以引入BehaviorDesigner插件来给敌人做表现,可以更好的管理AI的行为。
这次毕业设计使得本人充分认识到了书山有路勤为径,学海无涯苦作舟的道理,各行各业若想在行业中有所称就,就要付出比常人更加对的汗水,提升自己的技能水平,感触良多虽道阻且长,但仍一路前行。

致 谢

在本次论文设计过程中,感谢学校提供一次这样的学习机会,更加感谢从始至终一直悉心指导并给予帮助的指导教师黄志宇老师和苏畅老师。不论毕业设计还是论文书写阶段研究工作都是在黄志宇老师的细心指导下完成的,每一阶段都会与老师进行有关毕设项目的探讨与论文细节的修改,黄志宇老师总是能够给予我很多建设性的意见,使得受益匪浅。感谢所有授业解惑的老师,如果没有这四年的知识沉淀,相信毕设与论文完成的不会这么顺利,也正是因为这四年,得到了学识与内涵的双重提升,相信这是在校园以外所学不到的。所以感谢学校,感谢学院,更加感谢这一路以来有过如此帮助的老师们。感恩之余,希望各位老师可以对本人完成的毕业设计及论文多加评判与指正。最后,依然要对黄志宇老师的辛勤栽培和指导表示由衷的感谢,同时对学院全体领导及教研室的所有老师表示衷心的感谢,感谢老师们在大学期间的关心及教育。在此向全部老师致以真挚的谢意!最后也要感谢实习单位不管在精神上还是学习指导中给予我的鼓励和鞭策。

参考文献

[1]孔祥龙.Android平台连连看游戏控制逻辑设计与实现[J].电脑知识与技术,2017,13(03):206-208
[2]郗锐.浅谈电子游戏运营模式与机制设计[J].电脑知识与技术,2017,13(03):220-221
[3]玄令岐.基于UE4的迷宫逃生游戏设计[J].电子质量,2017(03):42-46
[4]钱俊廷. 手机游戏中卡牌游戏的设计与研究[D].长春工业大学,2016
[5]胡劲松. 基于Android平台的智力猜牌游戏设计与开发[D].东南大学,2016.
[6]王勤勤. 休闲益智手游界面设计视觉元素研究[D].东华大学,2017
[7]王琛瑜. 移动游戏界面视觉风格的研究与设计应用[D].东华大学,2017
[8]胡寅. 手机卡牌游戏“KeroStrike”业务逻辑层的设计与实现[D].齐齐哈尔大学,2016
[9]余艾琪. 沉浸式虚拟现实心理放松游戏的设计及体验研究[D].哈尔滨工业大学,2016
[10]李媛. 美术设计在手机游戏中的应用与研究[D].哈尔滨师范大学,2016
[11]程博文. 基于Unity引擎的策略游戏行星侵略的设计与实现[D].哈尔滨工业大学,2016
[12]何敏. 从游戏之外到游戏之中[D].湖南师范大学,2014
[13]Federico Fontana,Razvan Paisa,Roberto Ranon,Stefania Serafin. Multisensory Plucked Instrument Modeling in Unity3D: From Keytar to Accurate String Prototyping[J]. Applied Sciences,2020,10(4):22-24
[14]Lanming Jin,Qiao Xu. Computer simulation and system realization of jacquard weft-knitted fabric[J]. Journal of Engineered Fibers and Fabrics,2019,14:26-27
[15]Elizabeth Toriz. Learning based on flipped classroom with just-in-time teaching, Unity3D, gamification and educational spaces[J]. International Journal on Interactive Design and Manufacturing (IJIDeM),2019,13(3):25-28
[16]区泽宇,李晶,魏菊霞,严道葵,陈灿,许皓然.基于Unity3D游戏的设计与开发[J].无线互联科技,2019,16(23):62-63
[17]Unity 3D游戏关卡设计实训[J].计算机教育,2019(07):2
[18]김수균,김홍래,이원주. Design of 2.5D Survival Game using Inventory[J]. 한국컴퓨터정보학회논문지,2018,23(8)
[19]邓华丽.探讨基于Unity 3D游戏开发流程[J].电脑编程技巧与维护,2018(07):156-157+176
[20]李兵川.基于Unity 3D引擎角色扮演类游戏设计及开发[J].科技风,2018(15):11
[21]李兵川.基于Unity 3D游戏开发流程分析[J].山东工业技术,2018(07):148
[22]王龙,李韬伟,杨振发.游戏引擎研究与分析[J].软件导刊,2018,17(02):5-7
[23]刘克,李建方.基于Unity3D的内存优化的研究[J].中国传媒大学学报(自然科学版),2016,23(05):56-61
[24]陈丽萍.游戏引擎技术基础[J].安徽电子信息职业技术学院学报,2016,15(04):29-32
[25]桑琪,叶德建.基于Unity3D游戏客户端开发框架的设计与应用[J].微型电脑应用,2016,32(06):66-69+72

附录
public class StartPanel : UIForm
{
private Button returnButton;
private Button standardModeButton;
#region CallBack
///
/// Awake
///
void Awake()
{
//初始化组件
returnButton = transform.Find(“ReturnButton”).GetComponent();
//初始化组件
standardModeButton = transform.Find(“GameLevelMode/StandardModeBg”).GetComponent();
//添加组建点击事件
standardModeButton.onClick.AddListener(OnStandardModeClick);
returnButton.onClick.AddListener(HideModelPanel);
//订阅脚本关心事件
EventCenter.AddListener(EventType.ShowStartPanel, ShowStartPanel);
EventCenter.AddListener(EventType.HideStartPanel, Hide);
//默认隐藏
Hide();
}

/// <summary>
/// OnDestroy
/// </summary>
private void OnDestroy()
{
    returnButton.onClick.RemoveAllListeners();
    EventCenter.RemoveListener(EventType.ShowStartPanel, ShowStartPanel);
    EventCenter.RemoveListener(EventType.HideStartPanel, Hide);
}
private void ShowStartPanel()
{
    transform.gameObject.SetActive(true);
    EventCenter.Broadcast(EventType.ButtonShowOrHide,false);
}
private void OnStandardModeClick()
{
    //显示选择角色界面
    EventCenter.Broadcast(EventType.ShowCharacterPanel);
}
private void HideModelPanel()
{
    Hide();
    EventCenter.Broadcast(EventType.ButtonShowOrHide,true);

}
}
private void InitCard(CharacterType characterType)
{
if (characterType == CharacterType.Ironclad)
{
for (int i = 0; i < 5; i++)
{
haveCard.Add(allCards[0].Clone());
}
for (int i = 5; i < 9; i++)
{
haveCard.Add(allCards[1].Clone());
}
haveCard.Add(allCards[2].Clone());
}
EventCenter.Broadcast(EventType.UpdateALLCardList);
}
private void UseCard(CardVO card)
{
card.CardUse();
handCards.Remove(card);
disCard.Add(card);
EventCenter.Broadcast(EventType.UpdateALLCardList);
EventCenter.Broadcast(EventType.LoseCard, card);
}
private void LoseAllHandCards()
{
for (int i = 0; i < handCards.Count; i++)
{
disCard.Add(handCards[i]);
}
handCards.Clear();
EventCenter.Broadcast(EventType.UpdateALLCardList);
EventCenter.Broadcast(EventType.LoseAllCard);
EventCenter.Broadcast(EventType.LoseAllHandCardAnim, new Action(() =>
{
EventCenter.Broadcast(EventType.ChangeRoundCharacter, RoundManager.Instance.roundCount);
}));
}
public void GetCard()
{
int j;
CardVO card;
if (cardHeap.Count == 0)
{
WashCard(new Action(() =>
{
j = UnityEngine.Random.Range(0, cardHeap.Count);
card = cardHeap[j];
cardHeap.Remove(card);
handCards.Add(card);
EventCenter.Broadcast(EventType.UpdateALLCardList);
EventCenter.Broadcast(EventType.GetCard, card);
}));
return;
}
j = UnityEngine.Random.Range(0, cardHeap.Count);
card = cardHeap[j];
cardHeap.Remove(card);
handCards.Add(card);
EventCenter.Broadcast(EventType.UpdateALLCardList);
EventCenter.Broadcast(EventType.GetCard, card);
}
private void WashCard(Action OnComplete)
{
for (int i = 0; i < disCard.Count; i++)
{
cardHeap.Add(disCard[i]);
}
disCard.Clear();
EventCenter.Broadcast(EventType.UpdateALLCardList);
EventCenter.Broadcast(EventType.WashCardAnim, OnComplete);
OnComplete?.Invoke();
}
public void UpgradeCard(CardVO cardVO)
{
cardVO.Name += “+”;

    for (int i = 0; i < cardVO.CurrentValue.Count; i++)
    {
        cardVO.CurrentValue[i] = cardVO.UpgradeValue[i];
    }
    cardVO.Upgraded = true;
    //Refresh();
    EventCenter.Broadcast(EventType.UpdateALLCardList);
}
public void OnPassRoom()
{
    cardHeap?.Clear();
    disCard?.Clear();
    unuseCard?.Clear();
    handCards?.Clear();
    EventCenter.Broadcast(EventType.UpdateALLCardList);
    EventCenter.Broadcast(EventType.LoseAllCard);
}
private void InitCardHeap()
{
    for (int i = 0; i < haveCard.Count; i++)
    {
        cardHeap.Add(haveCard[i].Clone());
    }
    EventCenter.Broadcast(EventType.UpdateALLCardList);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/442708.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DFS(深度优先搜索)C++(Acwing)

代码&#xff1a; #include <iostream>using namespace std;const int N 10;int n; int path[N]; bool st[N];void dfs(int u) {if(u n){for(int i 0; i < n; i) printf("%d ", path[i]);puts("");return;}for(int i 1; i < n; i){if(!st…

启动项目报502怎么处理呢?

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

Qt自定义控件

自定义控件 目的&#xff1a;将多个控件或者窗口作为一个整体被多次复用。 操作方式 1.首先进行自定义的ui设计&#xff0c;以及对应的.h和.cpp文件 2.到要使用的UI界面上&#xff0c;从控件库中拖拽一个Widget控件 3.右键点击"提升为" 4.填写自定义实现的类名&…

IP地址定位技术的主要功能及应用

在互联网时代&#xff0c;IP地址定位技术成为了一项重要的技术&#xff0c;它通过分析用户的IP地址&#xff0c;确定用户的地理位置信息。IP地址定位技术不仅在网络安全、网络管理等领域有着重要的应用&#xff0c;也在商业、广告营销等领域发挥着重要作用。IP数据云将探讨IP地…

万用表数据导出变化曲线图——pycharm实现视频数据导出变化曲线图

万用表数据导出变化曲线图——pycharm实现视频数据导出变化曲线图 一、效果展示二、环境配置三、代码构思四、代码展示五、代码、python环境包链接 一、效果展示 图1.1 效果展示 &#xff08;左图&#xff1a;万用表视频截图&#xff1b;右图&#xff1a;表中数据变化曲线图&am…

SQL设计时增加说明列

后关闭sql Studio,然后打开注册表,注册表地址: 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SQL Server Management Studio\18.0_IsoShell\DataProject 如有版本不同,红色内容有所变化,修改内容如下: SSVPropViewColumnsSQL70,SSVPropViewColumnsSQL80 全修改为 1,2,6,7…

OJ_二叉排序树

题干 C实现 循环双指针法(一个指向父亲&#xff0c;一个指向待插入结点) #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <queue> using namespace std;struct TreeNode {char data;TreeNode* left;TreeNode* right; };void InsertBST(TreeNode* …

CubeMX使用教程(6)——ADC模拟输出

本篇将利用CubeMX开发工具学习ADC&#xff08;模拟输出&#xff09;的使用 我们还是利用上一章的工程进行二次开发&#xff0c;这样方便 首先打开CubeMX进行相关配置 通过查看G431RBT6开发板有关模拟输出部分的原理图可知&#xff0c;模拟输出用到的IO口是PB15和PB12 接着我…

llama-index调用qwen大模型实现RAG

背景 llama-index在实现RAG方案的时候多是用的llama等英文大模型&#xff0c;对于国内的诸多模型案例较少&#xff0c;本次将使用qwen大模型实现llama-index的RAG方案。 环境配置 &#xff08;1&#xff09;pip包 llamaindex需要预装很多包&#xff0c;这里先把我成功的案例…

Linux 之六:系统性能监控和挂载

系统性能 Linux系统中&#xff0c;有许多命令用于监测和分析性能指标。以下是一些常用的Linux性能分析命令&#xff1a; top&#xff1a;实时查看并监控CPU、内存以及各个进程的资源占用情况。htop&#xff08;需要安装&#xff09;&#xff1a;一个增强版的 top 命令&#x…

P3768 简单的数学题(莫比乌斯反演+杜教筛)

题目&#xff1a;P3768 简单的数学题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路&#xff1a; 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include<cstring> #include<cmath> #include<cti…

Java基础面试题(day 01)

&#x1f4d1;前言 本文主要是【Java】——Java基础面试题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&am…

【论文笔记】Mamba: Linear-Time Sequence Modeling with Selective State Spaces

原文链接&#xff1a;https://arxiv.org/abs/2312.00752 1. 引言 基石模型&#xff08;FM&#xff09;的主干网络通常是序列模型&#xff0c;处理任意的输入序列。但现代FM主要基于Transformer这一序列模型&#xff0c;及其核心的注意力。但是&#xff0c;自注意力仅能在上下…

JVM基本概念、命令、参数、GC日志总结

原文: 赵侠客 一、前言 NPE&#xff08;NullPointerException&#xff09;和OOM&#xff08;OutofMemoryError&#xff09;在JAVA程序员中扮演着重要的角色&#xff0c;它也是很多人始终摆脱不掉的梦魇&#xff0c;与NPE不同的是OOM一旦在生产环境中出现就意味着只靠代码已经无…

Git使用教程:入门到精通

Git使用教程&#xff1a;入门到精通 一、Git安装根据需求选择电脑位数安装&#xff1b;20231023210945建议这里先新建一个文件夹如&#xff1a;D:/Git&#xff1b;专门来存放Git安装包和后续Git代码&#xff0c;方便管理&#xff1b; 二、Git使用前的配置需要先创建自己的Gitee…

四桥臂三相逆变器动态电压恢复器(DVR)MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 简介 四桥臂三相逆变器 电路 的一般形式如图 1&#xff0c;为 便于分析 &#xff0c;将其等效成图所示的电路 。以直流母线电压Ud的 1&#xff0f;2处为参考点 &#xff0c;逆变器三相和零线相 输 出可等效成…

Kotlin dist downloading failed

现象&#xff1a; 在使用AndroidStudio编写Flutter项目时总是在工具的右下角提示错误信息 该问题通常在刚刚打开AndroidStudio时报出&#xff0c;但可以正常编译和运行flutter项目即Android项目 分析&#xff1a;Flutter项目组认为这是AndroidStudio工具平台本身的问题非Flut…

【CSP试题回顾】202009-2-风险人群筛查

CSP-202009-2-风险人群筛查 解题思路 主循环&#xff08;对每个查询&#xff09;&#xff1a; 使用一个布尔变量pass来标记风险人群是否至少一次进入了特定区域&#xff0c;以及一个布尔变量onlyOnce来确保停留计数 stayNum 在每次查询中最多只增加一次。内循环&#xff08;对…

站长必备溯源教程-绕过CDN查找背后IP的方法手段

绕过CDN查询背后真实IP方法&#xff1a; 方法一 DNS历史解析记录 查询域名的历史解析记录&#xff0c;可能会找到网站使用CDN前的解析记录&#xff0c;从而获取真实IP 相关查询的网站有&#xff1a;iphistory、DNS查询、微步在线、域名查询、DNS历史查询、Netcraft 方法二 …

Aop注解+Redis解决SpringBoot接口幂等性(源码自取)

目录 一、什么是幂等性&#xff1f; 二、哪些请求天生就是幂等的&#xff1f; 三、为什么需要幂等 1.超时重试 2.异步回调 3.消息队列 四、实现幂等的关键因素 关键因素1 关键因素2 五、引入幂等性后对系统的影响 六、Restful API 接口的幂等性 实战Aop注解redis解…