说明文档-基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发.doc

基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发

收藏

资源目录
跳过导航链接。
压缩包内文档预览:

资源预览需要最新版本的Flash Player支持。
您尚未安装或版本过低,建议您

基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发,基于,Unity3D,引擎,幻想,角色扮演,游戏,设计,开发
编号:145706887    类型:共享资源    大小:57.85MB    格式:ZIP    上传时间:2021-09-27 上传人:QQ14****9609 IP属地:陕西
40
积分
关 键 词:
基于 Unity3D 引擎 幻想 角色扮演 游戏 设计 开发
资源描述:
基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发,基于,Unity3D,引擎,幻想,角色扮演,游戏,设计,开发
内容简介:
密级:公开 基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发 Design and Development of the RPG Game Named “The fantasy of wind” Based on the Unity3D Game Engine 学 院:信息科学与工程学院专 业 班 级:计算机科学与技术1202班学 号:120405207学 生 姓 名:付 萌指 导 教 师:辛义忠 ( 副教授 ) 2016 年 6 月毕业设计(论文)指导教师审阅意见题目:基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发评语:指导教师: (签字) 年 月 日毕业设计(论文)评阅教师审阅意见题目:基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发评语:评阅教师: (签字) 年 月 日毕业设计(论文)答辩成绩评定计算机科学与技术专业毕业设计(论文)第 答辩委员会于2016 年 6 月 日 审定了计算机科学与技术1202班级 付萌 学生的毕业设计(论文)。设计(论文)题目:基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发 设计(论文)说明书共 页,设计图纸 张。毕业设计(论文)答辩委员会意见: 成 绩: 专业毕业设计(论文)答辩委员会 主任委员 (签字)摘 要游戏是人们生活中非常重要的一部分,人们使用游戏放松身心,通过游戏获取知识,透过游戏深刻思考。一款优秀的角色扮演游戏不仅仅能够为玩家带来愉悦的身心享受,更加能够为玩家带来一些深刻的内容,而这些内容显然要比长篇累牍的教诲深刻有效。Unity3D是一款专业游戏引擎,因具有其跨平台性能优秀、应用技术范围广、价格合理、易学易用等优点受到欢迎。课题使用Unity3D游戏引擎研究在角色扮演游戏的开发过程中需要使用的技术,并将之应用到课题的游戏设计中,在实践中学习相关技术并最终完成一款功能较为完善的角色扮演单机游戏。使用Unity3D作为引擎制作游戏系统,使用NGUI插件作为2D界面开发工具设计游戏界面,使用C#作为程序设计语言,实现基本的游戏功能和效果,并将游戏发布到PC平台。 在游戏中玩家将控制一名游戏人物在游戏世界中漫游,通过与怪物战斗、完成任务等方式获取奖励,通过购买装备、升级技能、改变设置等等方式强化人物,使之能够与更加强大的怪物进行战斗。游戏玩家通过保护一名村民漫游游戏场景完成游戏的核心任务。论文介绍详细介绍了游戏各项基本功能以及实现游戏各个模块功能时使用的相关技术或者方法,各个模块之间的联系或者调用方式,并给出实现这些功能的部分关键代码。关键词:游戏;Unity3D;游戏引擎;角色扮演游戏 Abstract Games are very important part in peoples life, people use games to relax, get knowledge in games, think deeply through playing. A perfect RPG game can not only make players enjoying it, but also can give players something deep, and this way is much more effective than boring teaching.Unity3D is a professional game engine, as it has strong points such as greate cross platform performance, wide range of application technology, lower price, easy to use, it is popular. The topic use the Unity3D game engine to learn the technology used in RPG designing, and use the technology int the topics game, learn the technology in practice, finally build a comprehensive RPG game.Using Unity3D as the game engine to process our game, using NGUI as the 2D interface develop tool, using C# as the programming language, implementing basic game features, and release the game to the PC platform. In this game, players can control a actor to roam in the scene, get rewards through fighting with monsters, finishing mission. Player can strengthen his actor with getting equips, learning skills or changing settings, make the actor enable to fight against the powerful monsters. Players can complete the core mission of the game by protecting a villager when he is roaming the scene.This paper describes the basic features of the game, the technology or methods which is used to implement the features, the connection and calls between features, and shows some key code of the game to implement the gameplay functions.Keywords: game; Unity3D; game engine; RPGIV 目 录摘 要IAbstractII第1章 引 言11.1 课题的意义11.2 课题内容与目标21.2.1课题主要任务21.2.2 预期目标21.3 国内外发展现状21.4 开发环境3第2章 游戏设计涉及的知识42.1 面向对象程序设计42.2 设计模式42.3 Unity3D相关知识4第3章 游戏场景与场景漫游的设计与实现63.1 设计与实现63.1.1 游戏场景设计63.1.2 人物移动设计63.2 与其它模块的联系8第4章 游戏人物的设计与实现94.1 属性设计与显示94.1.1 人物属性设计94.1.2 游戏主人公属性显示104.1.3 游戏其他单位属性显示124.2 游戏人物动画设置134.3 怪物AI144.4 与其它模块的联系15第5章 游戏技能的设计与实现165.1 被动技能的设计与实现165.1.1 被动技能的公共属性165.1.2 风王结界165.1.3 法力澎湃175.2 主动技能的设计与实现185.2.1 主动技能公有属性185.2.2 化相真如剑195.2.3王者的荣耀225.2.4 凄煌光临弹255.2.5 誓言胜利之剑285.2.6 剑气激荡315.3 游戏技能显示325.4 游戏技能管理355.5与其它模块的联系35第6章 游戏装备的设计与实现366.1装备简介366.1.1 装备通用属性366.1.2 装备技能的使用376.1.3 装备示例396.2装备获取与存放416.2.1 装备获取416.2.2 装备商店436.2.3 装备栏446.3装备合成446.4与其它模块的联系46第7章 其余加成效果的设计与实现477.1药品477.2剑刃与武器507.2.1 剑刃效果507.2.2 武器效果527.3击杀增益效果537.4与其它模块的联系53第8章 游戏剧情的设计与实现548.1 非战斗NPC与任务548.1.1 非战斗NPC548.1.2 游戏任务558.2剧情系统558.3与其它模块的联系56第9章 游戏数据管理579.1游戏存档579.1.1 存档与读档界面579.1.2 存档内容599.1.3文件存储与信息加密609.2其他文件信息619.2.1 传奇内容619.2.2 装备存储629.3与其它模块的联系62第10章 游戏功能设置的设计与实现6310.1系统设置6310.2音频管理6410.3小地图6410.4与其它模块的联系65第11章 游戏测试6611.1技能测试6611.2剑刃效果测试67第12章 结论69参考文献70致 谢72沈阳工业大学本科生毕业设计(论文)第1章 引 言1.1 课题的意义游戏,是人的本能之一。人们通过游戏进行学习,在游戏中思考人生,逐渐形成应对人生各种坎坷的意志。一款优秀的游戏,并不仅仅是给予玩家感官的刺激,更加是陶冶情操,深刻思想,获得知识的良好辅助。因为游戏本身的娱乐性质,可以大大地激发玩家的兴趣,而兴趣是学习的不二法门,所以在游戏过程中,人们并没有对学习产生或多或少的抗拒心理,注意力非常集中,并且能够主动地获取各种知识使得游戏能够更好地进展下去。如果,游戏能够提供具有深刻意义的知识,那么玩家就会很好地将这些知识记忆、理解甚至运用,学习效率会大大提升。游戏,能够承载的内容很多,通过游戏能够表达出来的内容很多,这不仅仅是用来消遣的内容,而是更加深刻的、更加具有表现力的述说。因为玩家在玩游戏的时候的专注,使得游戏中呈现内容能够对玩家带来更大的冲击。一款具有深厚人文背景、游戏性能优秀、具有丰富知识的游戏能够在使得玩家在游戏的过程中潜移默化地学习到很多重要的知识,而这种学习方式是轻松而有效的,其教学性和娱乐性结合使得游戏能够“寓教于乐”1-2。因此,设计优秀的、富于教育意义的游戏,是十分有意义的。程序,不仅仅是代码的组合,更是功能的集合;游戏,不仅仅是游乐的工具;更是思考的媒介、实现的方法、具有表现能力的应用;游戏引擎,不仅仅能够用于制作游戏,更是实现功能的一种手段。人对于游戏的专注和热情,如果能够被应用于其他的领域,能够产生极大的促进作用。游戏引擎因为能够制作具有很好的表现能力的程序,因此应用的领域也不会仅仅局限于游戏本身。游戏程序的应用范围很广,可以对人进行教育和培训,如消防模拟系统和逃生模拟系统的应用3-6;能够帮助科学研究,如可以通过Unity3D的物理引擎制作制作虚拟物理实验7,通过Unity3D的展示效果解决生物学家可视化的挑战8,通过构建虚拟城市帮助城市设计研究9;能够实现如三维变电站监控系统10等等具有现实意义的应用程序。通过游戏表达出来的内容更加容易被玩家接受,因此游戏也是很好的表达思想的方式。一款具有深刻思想内涵的游戏,能够引导游戏玩家进行思考,通过游戏中介绍的知识、游戏剧情、游戏画面、游戏音乐、游戏影像来为游戏玩家展现深刻的精神世界与思考。玩家在玩这类的游戏时,不仅仅是在玩游戏,更加是在与游戏的制作者们做着精神上的交流,并通过游戏知晓道理。真正有意义的游戏也许画面不够细致,也许游戏性能不够完善,但是要有深刻的思想内涵作为为支撑。游戏的发展也不会仅仅局限于图形图像技术、游戏操作媒介、游戏性能、游戏玩法等等,更加是在游戏中所要表达的内容。在这一点上,游戏与优秀的书、音乐、影视作品有着异曲同工之妙。1.2 课题内容与目标1.2.1课题主要任务本课题以Unity3D游戏引擎为基础,结合适当的模型,构建适宜的游戏场景,编写相应的游戏代码对模型进行操控,接收外部各种方式的输入,实现玩家对于游戏的基本操控。设计游戏剧情,游戏UI界面,游戏外部文件等等游戏设计必要内容使得游戏的信息量扩大,可玩性提升,并且随着剧情的编写,一些富有教育意义的知识和思想能够得以渗入,这些都将会用人物对话的方式展现出来。最终完成一款功能较为完善、具有一定可玩性的3D角色扮演游戏。1.2.2 预期目标(1) 完成游戏场景设计,实现人物在场景中的漫游;(2) 完成游戏UI界面制作,实现各个功能界面和界面之间的转换逻辑;(3) 成游戏脚本开发,实现游戏怪物AI、战斗系统、技能系统等游戏功能,为用户提供较为良好的游戏体验。1.3 国内外发展现状游戏的实现效果从无到有,再到华丽,游戏本身也逐渐从2D界面过渡到3D界面,以国产游戏仙剑奇侠传系列为例,第一代和第二代使用的是2D界面;到了第三部,游戏已经转变为3D游戏,但是效果和模型较为简单;第四部很好地改善了模型,效果也有了很大的提升;第五代和第六代逐渐提升游戏效果。值得一提的是仙剑奇侠传六使用的游戏引擎就是课题使用的游戏引擎。RPG游戏,即角色扮演游戏,是游戏玩家最支持的游戏种类之一,游戏制造商也十分愿意开发这类游戏。RPG游戏的玩家扮演游戏中的主人公,代入剧情、进行战斗、完成冒险、品味剧情。随着计算机技术的发展,角色扮演游戏从最初的表现形式仅仅为简单的文字和图形的游戏,发展到现在画面和剧情质量优秀的游戏,能够给予玩家更好的游戏体验。游戏玩家之所以青睐角色扮演游戏,是因为角色扮演游戏能够具有优秀的故事、精美的画面和玩家身临其境的感觉。在游戏过程中表现耐人寻味的故事,通过故事来阐述深刻的道理,这使得角色扮演游戏有着更加深远的发展意义。Unity3D是由Unity Technologies开发的专业游戏引擎11。 Unity3D游戏引擎的跨平台性能非常优秀,能够将游戏发布到诸多平台,例如:Windows、Android、iPhone、Windows phone 8。Unity3D游戏引擎有着入门简单、插件丰富、硬件支持丰富(如可以支持Kinect12)、使用C#和javaScript作为程序设计语言较为简单、强大的跨平台性等等诸多优点,游戏引擎发展迅速。此外,令人可喜的是Unity3D游戏引擎的价格只有约1500 美元13,价格合理,使得Unity3D正在逐渐成为游戏公司和虚拟现实公司的首选引擎。使用Unity3D游戏引擎开发的很多游戏如仙剑奇侠传OL、炉石传说、神庙逃亡2等游戏已经受到了游戏玩家的欢迎。市场对于Unity3D开发人员的需求正在逐渐增加。此外,Unity3D游戏引擎不仅仅可以用于制作游戏,还能够被应用于虚拟现实、增强现实、管理系统、训练系统、教学软件等应用的制作中,这使得Unity3D游戏引擎的应用范围宽广,具有很好的发展前景。1.4 开发环境课题所需的实验条件:PC机:CPU:Intel 酷睿 i3-2350m 2.30GHz 内存:4GB 硬盘:500GB 操作系统:Windows 7开发环境:Unity3D和MonoDevelop运行环境:PC机第2章 游戏设计涉及的知识2.1 面向对象程序设计游戏的设计使用了C#作为主要的程序设计语言14,在游戏设计的过程中大量使用了面向对象的程序设计思想15。面向对象的程序设计具有继承性、多态性和封装性的特点,非常适用于Unity3D的游戏设计。其中,继承性体现在了技能、装备药品等等的不同的类中,这些类都共有一个对应属性的基类,子类通过继承共同的父类或实现共同的接口来获取相同的方法或者调用方法的入口;多态性体现在了动态获取脚本组件中,在获取脚本组件时原本获取到的是父类,通过转换将父类转换为子类进行计算,而所有的子类可以通过调用父类获取得到;封装性是游戏设计中非常有趣味的部分,在游戏设计的过程中,努力做到类仅仅处理这个类所包含的内容,通过类之间的调用方法实现游戏效果。2.2 设计模式设计模式是前人大量编程经验的精华16,在游戏设计过程中大量使用了策略模式,其中最为典型的是剑刃效果。剑刃效果的实现依赖于剑刃效果的算法族,在游戏玩家选择剑刃效果时,即为选定当前使用的算法族群中的一个算法,并在战斗中触发这个效果。Unity3D中的脚本组件的添加与销毁与组合的思想十分类似。如果将游戏模型看成一个类,那么游戏模型上面的脚本即为这个类中包含的其他类的对象。游戏模型通过脚本组件的添加获取新的功能而不是通过大量的继承实现游戏功能的添加。2.3 Unity3D相关知识游戏设计使用的游戏引擎为Unity3D,是一款非常优秀跨平台游戏引擎。在游戏的设计过程中大量使用了Unity3D所提供的功能,如地形系统、导航寻路、粒子系统、物理系统、光照与声音从而实现游戏中丰富的功能和表现效果。(1) 地型系统:应用Unity3D的地形系统和相关的模型设计出游戏场景并实现场景漫游17-22,可以使用NavMesh组件各项选项设置与游戏脚本相结合的方法来实现人物在游戏场景中的自寻路功能23;(2) 动画系统: Unity3D游戏引擎的Legacy动画系统能够实现游戏中的动画的设置,使用Unity3D Animation组件和脚本控制动画的播放24;(3) 物理引擎:Unity3D游戏引擎中内置的physx物理引擎可以模拟物理效果。通过使用刚体、碰撞器、触发器等组件实现游戏中的物理碰撞效果、实现碰撞检测;(4) 粒子系统:通过使用大量微小的游戏物体组合成游戏中所需要的各种特效,使用Unity3D游戏引擎中particle system组件设置并控制粒子系统的效果25; (5) 射线:射线技术应用于3D虚拟世界中的定位和碰撞检测。其原理是从一个点向要一个方向发射无终点的线,当射线在轨迹中与物体发生碰撞,射线停止继续发射。使用这种技术在游戏中实现了定位、选择目标等重要的功能;(6) 协程:即协同程序,在主程序运行的同时进行另一段的逻辑的处理工作,这是基于Unity3D游戏引擎的“伪多线程机制”实现的模拟线程。在游戏的设计中,使用协程控制调用方法进行计算的时间26;(7) 音频剪辑:在Unity3D游戏引擎中导入音效和音乐,通过使用audio listener 和 audio source组件实现背景音乐的播放和音效的播放;(8) NGUI与GUI:Unity3D游戏引擎的NGUI插件提供强大的UI系统和事件通知框架,拥有性能高、使用方便、易扩展的特点。在游戏中使用NGUI制作复杂的2D界面。GUI,即图形用户界面,是Unity3D原生的GUI技术,因其简单易用的特征被游戏设计者使用。第3章 游戏场景与场景漫游的设计与实现3.1 设计与实现游戏场景是游戏必要的基础,游戏主人公、怪物、效果都需要在游戏场景中显示。在这个部分的设计包括游戏场景的设计和人物移动的设计,以保证人物能够进行场景漫游。3.1.1 游戏场景设计 Unity3D游戏引擎内置的地型系统允许手工绘制地型,能够通过使用内置工具创建地型,设置游戏场景的高低起伏和颜色。在场景中可以摆放树木植被,放置建筑物模型,并且进行相关设置。课题所需要的游戏场景使用这种方式进行绘制。绘制完成后对游戏场景进行自动导航烘焙使其能够支持导航组件。完成后的场景的一部分如图3-1所示。图3-1 部分游戏场景3.1.2 人物移动设计本课题使用Unity3D自动寻路组件作为移动判断的依据,编写相关的移动脚本调用自动寻路组件,并使用其相关方法设定目标位置。使用射线与射线撞击的方式进行目标的判断。游戏玩家点击鼠标右键,游戏主摄像机会模拟一条射线发射,同时获取射线命中的单位的相关信息,相关脚本接收到这个信息就可以作出相应的判断并采取不同的动作,不完整的射线碰撞与目标选定的脚本代码作为示例如下:Ray mRay = Camera.main.ScreenPointToRay (Input.mousePosition);/发射射线RaycastHit mHi;/射线命中单位if (Physics.Raycast (mRay, out mHi) /如果命中了一个目标if (mHi.collider .tag = earth|mHi.collider .tag = untagged) /检查标记Vector3 destenation = new Vector3 (mHi .point .x, mHi .point .y, mHi .point .z);/计算位置this.GetComponent ().SetDestination (destenation); /设定位置 /做出相关动作 不同的人物有不同的标记,通过标记可以判断出当前所选择的目标是什么,然后根据这个目标做相应的设置。例如,当目标是地型的时候,移动停止距离为0,而目标是怪物的时候,移动停止距离与人物和怪物的攻击范围有关。当选择了一个目标之后,人物就会面向目标位置,同时向这个目标进行移动。在移动的同时,人物模型就会播放相关移动的动画效果,产生人物“奔跑”向目标的效果,这个效果如图3-2所示。图3-2 游戏人物移动特别地,游戏主人公还有较为特殊的一些移动方式,例如“闪现”、“加速”、“飞行”等等,其中“闪现”、“加速”等移动方式与普通移动方式的原理相同,都是使用自动寻路组件设定目标,然后加速移动或者位移到相应的位置。而“飞行”则使用较为不同的移动方式,在飞行的移动方式下,人物移动无视任何碰撞。这是因为使用了不同的移动代码,这些代码没有对位置的限制。“飞行”的效果如图3-3所示,代码示例如下:this .transform .Translate (Vector3.forward *Time .deltaTime*flySpeed );/向前移动图3-3 游戏人物飞行由于自动寻路组件的限制,游戏人物在移动的过程中受到地型的限制,这些限制包括坡度、高度等,只有在一定值范围内的地型才可以被行走。人物在没有“飞行”时会受到地型的阻碍,移动时会因为障碍物的限制而停止或者绕行。对于某些障碍物,移动是无法跨越的,此时可以使用“跳跃”来进行取消寻路组件的效果并进行强制移动。当“跳跃”结束之后,人物会重新受到寻路组件的限制,如果此时人物进入的不可进入的位置,人物就会再一次强制位移到可移动到的位置。3.2 与其它模块的联系(1) 场景地型是承载模型的载体,所有的可见模型初始位置都在地型上;(2) 怪物AI中的移动也使用自动寻路组件实现,其目标位置由AI给出;(3) 自动寻路组件的使用不仅仅在场景漫游中使用,在部分技能效果中也有。例如击飞特效,其原理就是关闭目标自动寻路组件使其在一段时间无法主动移动,同时强制使目标向上位移;(4) 游戏人物在场景漫游中可能会修改部分属性值。第4章 游戏人物的设计与实现4.1 属性设计与显示4.1.1 人物属性设计游戏人物的属性是游戏人物在游戏中计算的依据,同时也是不同发展方向的表现。游戏人物的升级、购买装备和药品、获取增益和减益效果都是在修改这些属性,使得游戏人物有不同的表现。游戏人物主要属性参数的功能介绍如下:(1) 名字:游戏主人公的名称;(2) 等级:游戏人物的等级;(3) 经验值:当前游戏人物的经验值;(4) 生命值:人物的生命点数,如果耗尽(小于0)人物就会被判定为死亡;(5) 生命上限:人物的生命最大值;(6) 生命偷取:普通攻击的同时能够偷取到的生命值;(7) 生命恢复:每秒的生命恢复值;(8) 生命反噬:法力耗尽的生命反噬百分比,这个伤害针对透支的法力;(9) 法力值:人物当前法力,使用技能消耗,如果透支就会反噬生命;(10) 法力上限:人物的法力最大值;(11) 法力偷取:普通攻击的同时能够偷取到的法力值;(12) 法力回复:每秒的法力恢复值;(13) 物理护甲:针对物理攻击的防御值,有效上限为2000;(14) 魔法抗性:针对魔法攻击的防御值,有效上限为2000;(15) 物理穿透:物理攻击中能够无视物理护甲的值;(16) 法力穿透:魔法攻击中能够无视魔法抗性的值;(17) 物理反伤:受到攻击后回敬给攻击者的物理伤害;(18) 魔法反伤:受到攻击后回敬给攻击者的魔法伤害;(19) 一击必杀率:一击击败对手的几率;(20) 暴击率:造成超常伤害的几率;(21) 暴击伤害倍数:超常伤害对于普通伤害的倍数;(22) 闪避率:闪避掉攻击的几率;(23) 格挡率:格挡攻击,造成即将到来的伤害的真实减免;(24) 格挡伤害减免:发生格挡时能够减免的伤害最大值;(25) 转身速率:人物的转身速度;(26) 移动速度:人物的移动速度;(27) 攻击速度:攻击速度,包括近战动画速度和远程弹矢发射时间间隔;(28) 物理攻击力:人物的物理方面的攻击能力,受到物理护甲的钳制;(29) 法术强度:人物的法术方面的攻击能力,受到魔法抗性的钳制;(30) 生命转化:造成物理伤害时,造成伤害转化为自身生命值的百分比;(31) 法术吸血:造成魔法伤害时,造成伤害转化为自身生命值得百分比;(32) 冷却缩减:技能填充时间的百分比减免;(33) 普攻伤害加成:普通攻击造成伤害时获得的额外伤害百分比;(34) 攻击范围:人物能够进行近战攻击的最大范围;(35) 远程攻击射程:人物能够进行远程攻击的最大范围;(36) 额外护盾:人物的护盾值,可抵挡伤害,上限为最大生命值的40%。4.1.2 游戏主人公属性显示游戏主人公的属性相对于游戏怪物的属性更多,其详细的属性值可以在人物属性面板和GUI属性窗口上得到,如图4-1和图4-2所示。在基本NGUI界面的左侧和下侧也会显示部分关键属性的值,如图4-3所示。同时,玩家可以在游戏窗口中查看由生命值、法力值和护盾值组成的GUI显示信息如图4-4所示。图4-1 游戏人物属性在人物属性面板中显示图4-2 游戏人物属GUI窗体显示游戏人物的属性更新均为实时更新,当游戏人物在某种情况下修改了属性值,这些属性即可在显示面板中显示出来。在这里使用Unity3D的Update方法在每一帧中更新所显示的值。某一个NGUI的Label显示的示例代码如下:void Update ()/每一帧更新this.gameObject .GetComponent ().text = show;/显示内容游戏人物的生命值、护盾值、法力值能够实时显示在屏幕中,能够较为直观显示当前游戏主人公的生命、法力情况。在这里使用的是Unity3D的GUI显示方法。编写脚本创建GUIBox,通过改变GUIBox的长度模拟显示人物当前值占总值的百分比情况。生命值在显示的同时也会表现出不同的颜色,处于优化考虑,生命值显示所使用的颜色仅为4种。使用GUI显示游戏人物生命值百分比的显示效果如图4-4所示,其不完整的示例代码如下:void OnGUI() /GUI方法GUI .BeginGroup (new Rect (c.x - 100, c.y, 200*viewPlas, 100*viewPlas);/建立一个GUI盒子 GUI.Box (new Rect (30, 21, 155*viewPlas, 14*viewPlas), );/背景 GUI.backgroundColor = theHpColors(int)(3*peopleMain.HP /peopleMain .HPmax); /背景颜色重新设置GUI.Box (new Rect (30, 22, 150 * peopleMain .HP / peopleMain .HPmax*viewPlas, 12*viewPlas), , GUIShowStyleForHp); /显示生命值 GUI .EndGroup ();/盒子结束图4-3 部分游戏人物属性在基本界面中显示图4-4 游戏主人公的生命值、法力值和护盾值的GUI显示4.1.3 游戏其他单位属性显示游戏中除了游戏主人公也会有其它的单位,如怪物、木桩等等。玩家可以通过鼠标点击和鼠标悬停两种方式获得这些单位的信息。其使用的方式与上述GUI界面和NGUI界面显示方法相同,选择目标的方式为射线法。其中鼠标悬停时可以或读到的信息可以有两种,其一是只显示生命值百分比和名称,其二是附加一些关键属性的值,其不同的显示结果参见图4-5。使用NGUI显示方法能够显示目标单位的一些关键基本属性,但是由于NGUI显示界面仅有一个,所以在玩家需要频繁获取单位信息的时候灵活性稍有不足,其显示结果可参见图4-6。图4-5 鼠标悬停显示怪物信息图4-6 怪物信息面板4.2 游戏人物动画设置在游戏过程中,游戏人物始终在播放某一个游戏动画效果。每一个游戏人物均有一些不同动作的游戏动画,包括战斗动画、奔跑动画、静止动画和死亡动画,此外拥有特殊的技能的单位也拥有技能的施放动画。游戏人物的动画资源来自于互联网免费资源,游戏设计中没有针对游戏动画进行设计。Unity3D的Animation组件能够实现游戏人物动画的播放,将游戏的动画资源保存到Animation组件的数组中,通过下标或者动画的名字访问并播放动画。在游戏中利用Animation组件播放动画如图4-7所示。图4-7 以游戏人物奔跑动画效果游戏人物动画播放由能够播放动画的游戏单位上面的脚本与Animation组件完成。游戏主人公的动画播放控制代码与其自动寻路代码结合,而怪物的动画控制代码与怪物的AI结合。值得注意的是,游戏人物的战斗过程即为动画播放的过程,在人物播放攻击动画的同时进行碰撞检测,从而实现攻击命中的判断,为接下来的属性改变计算做准备。使用字符串对不同的游戏动画进行区分,根据游戏人物的状态获取应播放的动画名称,传入动画名称进行播放和动画切换。游戏人物动画播放的示例代码如下:if(isJumping) /判断状态NowPlayAnimationName = jumpAnimationName;/修改应播放动画名称/其他工作playerMode .animation .Play (NowPlayAnimationName);播放动画4.3 怪物AI游戏中由计算机控制的怪物的AI是不可或缺的游戏组成部分。游戏中的AI能够控制具有AI的怪物进行自主的行为控制和状态转换25,达到游戏玩家与计算机之间更好的游戏效果。游戏AI实现了怪物对游戏主人公的侦查、追击和攻击。其具体的工作流程为:当游戏主人公进入怪物的侦查范围,怪物会面向游戏主人公,但是不会追击;当游戏主人公进入了怪物的追击范围,怪物就会追击;当游戏主人公被追至怪物的攻击范围,怪物就会停止追击并进行攻击。当游戏主人公逃离怪物的侦查范围,怪物就会丢失目标,进入随机动作状态,即初始状态。其中,怪物在侦查时对不同目标有计算的优先等级差异:怪物最优先攻击游戏主人公的召唤物,其次是游戏主人公本身,最后是游戏主人公所要保护的对象。AI侦查的实现中使用了相交球的方法,检测身边所有的模型,从中筛选AI能够进行攻击的目标种类,最后根据优先级进行取舍,确定AI的目标。确定AI的目标之后,怪物就会进行思考。根据怪物与目标之间的距离做出追击、攻击等等不同的动作。其示例代码如下:/判断敌人与主角之间的距离float distance = Vector3.Distance(player.transform.position,this.transform.position);if(distance = runAfterDistance)if(distance attackDistance)/攻击animation .Play(AttackAnimaName);else/继续追击else/停止追击当怪物的目标逃离怪物的侦查范围或者怪物的目标被击败,怪物就会丢失目标,重新进入侦查状态,在侦查到一个新的目标之前,怪物就会随机做出一些动作,如奔跑和攻击动作等等。此外,在怪物丢失目标的状态下,怪物的移动速度很低,不会离开自身所在位置一定范围很远。怪物不会随时随地进行侦查,只有在目标丢失的情况下才会进行侦查。两次侦查之间有一定的时间间隔,且时间间隔与怪物的等级有关。换言之,高等级的怪物很难偷袭而低等级的怪物比较容易偷袭成功。此外,怪物的追击范围和攻击范围并不统一,尤其是攻击范围与怪物本身的攻击范围有关。4.4 与其它模块的联系(1) 这个部分介绍了游戏人物的属性和游戏人物属性的显示。这些属性在游戏的主体即游戏战斗部分会得到大量的更新;(2) 在场景漫游的特定情况下也会修改游戏人物的属性值,例如人物跳跃的时候撞在墙上就会削减生命值;(3) 在特定技能生效的情况下游戏人物的动画在一定时间内不受玩家控制;(4) 怪物AI调用怪物的自动寻路组件确定怪物的移动目标。第5章 游戏技能的设计与实现游戏技能是游戏设计中重要的部分,玩家使用技能在战斗中产生不同的战斗效果。课题中,游戏的技能分为两种,被动技能和主动技能。被动技能无需使用快捷键,计算机自动触发和执行技能的效果。主动技能为玩家主动使用的技能,通过点击技能快捷键使用相对应的技能。主动技能的设计要比起被动技能更加复杂,其关联的游戏技能管理单元和显示界面内容更多。5.1 被动技能的设计与实现游戏的被动技能效果是通过计算机计算得出的,玩家无法主动使用,这一类的技能设计难度较为简单。在游戏设计的过程中,将不同被动技能设计为预设物,通过改变预设物即可修改人物的被动技能。被动技能的实现原理是通过被动技能脚本实时检测游戏人物的属性值,根据属性值计算得出相应的技能结果。在设计过程中制作了不同了被动技能预设物,这些技能均有不同的实现脚本,在这里介绍两个被动技能作为示例。5.1.1 被动技能的公共属性被动技能虽然功能各不相同,触发方式多种多样,但是仍有一些共有属性,陈列如下:(1) 技能名称:这个技能的名称;(2) 技能贴图名称:技能显示在NGUI界面中的图片,对应图集中图片名称;(3) 设置位置:被动技能生效位置,如身体、武器等;(4) 脚本名称:被动技能的脚本名称,使得脚本能够动态添加或销毁;(5) 技能特效:允许为空,为技能生效时显示的特效效果。5.1.2 风王结界这是一个护盾类型游戏被动技能,其在游戏中的功能为“获得一个吸收最大生命值7.5%伤害的护盾,护盾被击破之后进入冷却期,冷却结束后刷新护盾值上限,冷却时间25秒。如果10秒内没有受到攻击,护盾会修复,但不会刷新上限值。”,被动技能生效时的效果如图5-1所示。图5-1 被动技能“风王结界”存在时的效果这个被动技能的实现需要两个脚本,即护盾脚本和检测脚本。护盾脚本用于检测人物护盾受到的伤害,当这个伤害超过自身护盾值时,判断进入冷却时间;检测脚本负责实时检测护盾是否被击破,并完成冷却时间的计算。其中,判断护盾所受到的伤害利用了统计模块的伤害统计数值,这个值为公有静态值,在护盾脚本中实时检测,当收到的伤害总值比护盾生成时收到的伤害总值与护盾值总和高,则认为这个技能的护盾已经破裂,需要进入冷却时期。判断是否受到攻击的方法为简单的碰撞检测,如果在一定时间长度没有受到来自怪物武器的碰撞,则视为没有受到攻击。其碰撞检测的示例代码如下:void OnCollisionEnter(Collision collisioner)/碰撞检测方法,事件处理程序if (collisioner.gameObject .tag = monsterweapon)/如果碰撞物是怪物武器/刷新等待时间5.1.3 法力澎湃这是一个回复类型的技能,其在游戏中的功能为“回复1%最大法力值/5秒。”技能效果简单,为每隔5秒钟回复最大法力值的1%。在这里为了防止卡顿,没有使用协程,而是使用数值和简单的计数器实现。计数器的实现代码在游戏中被大量的使用,其示例代码如下:timer -= Time .deltaTime;/减少一定的时间值if (timer 0) /到达一定时间timer =timerBasic ;/更新时间值 /做相关的工作5.2 主动技能的设计与实现游戏技能的设计是游戏设计过程中最为复杂和精彩的部分之一,每一个主动技能都包含了很多不同的效果,经历了大量的测试和修改最终成型。游戏中的主动技能被制作成为预设物,被管理在游戏人物的技能数组中,其位置和内容可以随意改变,这为游戏开发提供了很好的可修改性,当一个新的技能被制作完成之后,只需要替换相应位置的技能预设物既可以替换技能。5.2.1 主动技能公有属性游戏主动技能比起游戏被动技能较为复杂,每一个技能都有不同的实现方法,所使用的脚本也不相同。但是所有的游戏主动技能均继承自游戏主动技能基类,其中包含了游戏技能共有的大量属性,介绍如下:(1) 技能名称:这个技能的名称;(2) 贴图名称:技能显示的图片名称,对应图集中的图片名称;(3) 技能基本介绍:技能的简略信息介绍;(4) 范围类型:技能影响范围,如直线、圆形范围、圆形范围选择等等;(5) 作用范围:技能的影响范围;(6) 技能等级:当前技能的等级;(7) 技能等级上限:技能最大等级;(8) 法力消耗:使用技能时消耗的基础法力值;(9) 法力消耗等级提升:法力消耗随等级提升增加的值;(10) 初始物理效果:技能生效时的固定物理加成;(11) 初始物理效果等级提升:初始物理效果随等级提升增加的值;(12) 物理攻击力加成:技能生效时针对物理攻击力的加成;(13) 物理攻击力加成等级提升:物理攻击力加成随等级提升增加的值;(14) 初始魔法效果:技能生效时的固定魔法加成;(15) 初始魔法效果等级提升:初始魔法效果随等级提升增加的值;(16) 法术强度加成:技能生效时针对法术强度的加成;(17) 法术强度加成等级提升:法术强度加成随等级提升的值;(18) 冷却时间:两次使用本技能所需要的时间间隔;(19) 持续时间:技能生效时间长度;(20) 持续时间等级提升:持续时间随技能等级提升增加的值;(21) 音效:使用技能是播放的音频剪辑;(22) 技能显示按键:技能对应的NGUI界面显示按钮。除以上这些技能最基本的属性之外,每一个技能还会有更多技能专有的属性,这些属性将会在介绍这些技能时介绍。5.2.2 化相真如剑游戏技能“化相真如剑”是游戏中非常实用的物理攻击技能,其主要的功能是对单体对手造成削弱和伤害或者对一条直线上的对手造成伤害。技能的介绍如图5-2所示。图5-2 主动技能“化相真如剑”的技能介绍如介绍所示,这个技能可以分为两个部分。第一部分是近战攻击,造成护甲削弱和持续伤害的效果,这个技能效果可以大幅度削弱拥有高护甲和高生命恢复的目标,并且近战攻击效果支持暴击和剑刃效果,能够随着暴击的发生大幅增加技能伤害。技能近战效果如图5-3所示。技能的第二部分是一个伤害递减的直线攻击,虽然附加攻击特效如剑刃效果,但是不支持暴击,也不会为目标附加护甲削减和持续伤害的效果。直线攻击的射程很远,适合一次性攻击大量的目标或者对目标进行骚扰。近战攻击转直线攻击需要消耗额外的法力值,这个法力值与激活近战攻击效果消耗的法力值有关。直线攻击效果如图5-4所示。“化相真如剑”的实现过程中应用到了很多典型的实现方法,技能的实现包括4个部分:技能使用部分、近战攻击部分、目标削弱部分和直线攻击弹矢部分。图5-3 主动技能“化相真如剑”的近战攻击效果图5-4 主动技能“化相真如剑”的弹矢效果技能使用部分是玩家使用技能时调用的部分,当玩家按下技能快捷键时调用技能使用方法。这里包含技能能否使用的判断、使用技能的法力消耗、技能效果的显示等诸多细节。近战攻击部分的实现由一个附着在游戏主人公武器上面的脚本实现。当人物武器命中一个目标时,将这个目标同样视为这个技能攻击的目标,并附加目标削弱部分的脚本。游戏设计中大量使用了动态添加脚本的方法实现不同效果的独立计算和销毁。可以通过在附加脚本之后修改对应脚本属性值的方法对脚本进行设置,使这些脚本更加富有多变性。值得注意的是,这些设置会在脚本初始化之前完成。动态添加脚本示例代码如下:sword .AddComponent(swordBuff);/添加脚本sword .GetComponent ().effect =this.effect ;/修改属性目标削弱部分是一个脚本,在脚本初始化的同时削减目标护甲,同时在脚本销毁的同时将削减的护甲归还。同时,在脚本更新方法中,不断对本脚本所附着的目标进行伤害。目标削减脚本中初始化削减在销毁时归还的目的是模拟真实的削减效果,并防止误差。在游戏过程中,某一个目标有可能会有大量的削减效果同时存在,必须保证每一个削减效果都有属于自己的恢复方法,而不是统一处理,保证误差最小。目标削减代码的示例如下void Start () /削减(在创建时调用)void OnDestroy()/回复(在销毁时调用)直线攻击弹矢部分的目的是像游戏人物当前正前方发射弹矢,并且根据弹矢命中的目标进行相关计算。其实现方法使用了动态创建预设物的方式。事先将弹矢制作成为预设物,在发射弹矢时创建一个预设物实例。为了保证弹矢的可穿透性,在这里使用的是触发器而非碰撞器。创建预设物以及触发器检测的事件处理方法示例代码如下:GameObject effecter = (GameObject)Instantiate(bullet);/创建预设物void OnTriggerEnter(Collider collisioner)/触发器检测方法如果只是发射弹矢,弹矢就会毫无预兆地向前发射,无法很好地模拟游戏人物的动作。为了保证弹矢的发射与游戏动画的协调,这里使用了简单的协程实现效果。当游戏人物播放攻击动画一定时间之后,弹矢会从游戏人物的武器上发射出去。这样,再施放技能和技能生效之间就会有一个很短弹矢能够被察觉到的时间差,这会很好地提供游戏玩家的可能的操作细节和游戏可玩性。使用协程控制弹矢发射时间的示例代码如下:IEnumerator makeDamageStep2()/协程 /相关计算Nav.changeNowPlayAnimationName(Attack);/播放攻击动画yield return new WaitForSeconds (this.transform .root .animation Attack.length/(3*peopleMain .attackSpeed);/等待一定时间/发射弹矢Nav.changeNowPlayAnimationName(idle);/切换动画StopCoroutine (makeDamageStep2);/关闭协程5.2.3王者的荣耀游戏技能“王者的荣耀”是游戏中非常强劲的技能,集回复、攻击、防御于一体,并且接受物理攻击力和法术强度双重的加成,可以是游戏人物在短时间内爆发出非常惊人的伤害,提升高额的防御能力。但是由于技能冷却时间较长,法力消耗较多,在冷却缩减和法力上限不足的情况下使用会造成大量的消耗。此外值得注意的是,第一段的法力消耗是人物当前法力值的15%,而第二段法力消耗是人物最大法力值的5%,这使得“王者的荣耀”的技能法力消耗保持在一个很大的数值。其技能介绍如图5-5所示。图5-5 主动技能“王者的荣耀”的技能介绍“王者的荣耀”的实现由以下几个部分组成:技能使用部分、自身加强部分、“辉耀”效果部分。玩家在使用技能时,调用的是技能使用部分的技能使用方法,从而动态地为游戏人物添加自身加强部分的脚本,获取相应的技能加成、在效果结束之后或者制动施放“辉耀”时调用“辉耀”效果部分的脚本。这个技能的生命恢复效果与游戏人物已损失的生命值百分比有关,生命消耗越多,生命恢复效果也就越好,设定的一次性回复生命最大值为人物当前最大生命值的20%,其中3%固定回复,17%按照已损生命值百分比进行计算。技能对于攻击力、法术强度的加成值是一致的,同样地对于护甲和魔法抗性的加成值相同。技能接受物理攻击力和法术强度双方面的加成收益,其中,物理攻击力的加成效果更加偏向于提升供给能力,而法术强度的加成效果在防御加成效果中更加明显。实现加成效果的方式为动态附加脚本组件的方式,定义组件持续的时间,在游戏人物装载组件时获得技能加成效果,并播放游戏技能特效,在组件销毁时去除技能的加成效果,删除技能特效。其中,技能效果脚本的销毁使用了获取脚本的方法。“王者的荣耀”技能激活效果如图5-6所示。图5-6 主动技能“王者的荣耀”的激活后的效果“辉耀”效果的实现使用了相交球的方法,检测游戏人物周围一定半径内所有的单位,如果这个单位是可以被这个技能命中的,就在这个单位身上加载击飞和伤害脚本组件,造成群体伤害和击飞的效果。“辉耀”发动的效果如图5-7所示。图5-7 主动技能“王者的荣耀”的“辉耀”效果“辉耀”效果能够额外吸收15生命值,此外的伤害类型是魔法伤害,因此能够得到法术吸血的增益加成,即当法术吸血很高时,可以通过使用这个技能在敌人人群中获得大量的吸血效果。此外,辉耀效果的伤害得益于已损失的法力值,并且基于法力值的计算在法力消耗之后,使得这个加成固定会拥有最大法力值5%的增益。“辉耀”效果命中一个单位之后,会对目标单位造成击飞效果,在一定时间内使其无法移动,只能向上空做运动。“辉耀”命中目标后的击飞与生命恢复效果如图5-8所示。图5-8 主动技能“王者的荣耀”的“辉耀”击飞效果范围攻击的实现大量使用了相交球的方法,“辉耀”效果也是如此。相交球的原理大致为从球心开始检测球内所有的游戏模型,并获取到这些模型的对象数组。使用获取到的对象数组对元素进行判断。其示例代码如下:Collider emys = Physics.OverlapSphere (this.transform .position, 7);/以自身所在位置为球心构建相交球,半径为7,获取球内所有模型if (emys i.tag = monster)/使用tag标记判断元素类型(tag已设定完成)在获取到目标元素之后,为目标元素附加击飞脚本,关闭目标单位的自动寻路导航组件,并强制目标向上移动一段距离,实现击飞效果的示例代码如下:if (this.gameObject .GetComponent () /判断是否有导航组件this.gameObject .GetComponent ().enabled = false; /关闭导航组件this.gameObject .transform .Translate (transform .up *2.5f*Time .deltaTime); /强制移动目标模型5.2.4 凄煌光临弹技能“凄煌光临弹”是一个使用简单但是设计较为复杂的远程攻击技能,并且使用难度较大。这个技能的效果集指向性远程伤害、生命恢复、护盾、法力回复于一身,配合较高的法术强度和法术吸血能够在打出惊人伤害的同时回复大量的生命。这个技能共有三种基本的使用方法:(1) 在目标选定范围内选择目标进行攻击;(2) 对当前攻击目标或当前追击目标进行攻击;(3) 随机选定一个身边的目标进行攻击。其中,第一种方法在混战中比较难以操作,并且有法术释放距离的限制。第二种能够对指定目标进行远距离狙击,发射的弹矢受到释放距离和持续时间的限制。而第三种方式是随机攻击,无需任何操作。其技能介绍如图5-9所示。图5-9 主动技能“凄煌光临弹”的技能介绍技能的实现分为两大部分:技能的实现和技能弹矢的实现。首先介绍技能弹矢的实现。游戏中使用特定的脚本控制弹矢,使得弹矢能够朝向目标飞行并在一定时间内追踪目标,并在与目标距离足够小的时候自行销毁,创造伤害的后续的加成效果。使用技能时发射弹矢的效果如图5-10所示。图5-10 主动技能“凄煌光临弹”发射弹矢攻击效果弹矢的追踪目标方法使用在更新方法中,使得弹矢能够实时更新自身的位置和朝向,达到追踪的效果。追踪的示例代码如下:transform.position=Vector3.MoveTowards(this.transform.position,aim .transform.position, 2.15f);/以2.15的速度向目标移动在游戏设计中,弹矢的命中可以使用碰撞检测。但是为了这个技能的灵活性,游戏最终选择使用与目标的距离作为命中的依据。因为在弹矢移动中有可能会偶然命中其他非目标单位,导致造成错误的伤害。在游戏中,弹矢的销毁使用距离检测的办法,而弹矢附带的伤害和加成效果在弹矢销毁的时候产生。示例代码如下:if(Vector3 .Distance (this.transform .position,aim .transform .position)0.1f) Destroy (this.gameObject); /距离足够小就认为命中,销毁弹矢void OnDestroy()/调用销毁方法的入口,所有销毁时造成的效果在此调用“凄煌光临弹”的技能在使用时分为以下几个步骤:激活技能、选定目标、面向目标移动、到达可攻击范围时发射弹矢。其中,可以在面向目标移动时再次激活技能,向目标发射弹矢或随机攻击一个距离游戏人物比较近的对手。在这个技能的实现中,亦是分为以下几个部分。激活技能:当游戏玩家按下技能快捷键技能被激活,进入到选定目标状态。选定目标:在一定时间内等待玩家再次激活或者选择一个目标,技能目标选定范围如图5-11所示。选择目标的方式仍然是射线法。当选定一个目标后进入移动状态。改变游戏人物移动目标示例代码如下:this.transform.root.gameObject.GetComponent().SetDestination(mHi.transform .position);/设定目标this.transform.root.gameObject.GetComponent().stoppingDistance=maxDistance-2;/设定停止距离移动状态:向目标移动,这里使用的方法是向游戏人物移动模块传入目标的位置,设定技能的法术释放范围为停止距离,这样就可以是游戏人物面向目标奔跑。游戏人物在奔跑过程中实时检测与目标的距离,示例代码如下:if(Vector3.Distance(this.gameObject .transform .root .position ,mHi .collider .transform .position)maxDistance)/发射弹矢图5-11 主动技能“凄煌光临弹”目标选择范围发射弹矢:创建弹矢并设置弹矢的目标。弹矢被这设置为预设物,发射弹矢即为实例化预设物,在实例化之后设置弹矢的目标属性。在游戏中可以再次激活这个技能攻击当前目标或者攻击距离自身比较近的目标。攻击当前目标的方法很简单,实例化弹矢然后将弹矢的目标属性赋值为自身目标,其攻击效果如图5-11所示。而攻击距离较近的目标使用了相交球的检测方法。检测身边可以被这个技能攻击的目标,为目标与游戏人物距离排序,从中选择目标发射弹矢。值得注意的是,“凄煌光临弹”的斩杀效果是模拟出来的,而不是真的斩杀。当弹矢命中目标之后,通过穿透与防御等等属性的计算,得出本次攻击的最终真实伤害,如果这个伤害大于目标当前的生命值,就认为这个弹矢击杀了这个怪物。而此时,怪物还没有真正死亡,直到下一帧计算完毕,怪物的属性管理单元发现自身生命值为负数,怪物才真正进入死亡的状态。弹矢有持续时间,其实现的方法为定时销毁。因此弹矢有可能无法命中目标。当弹矢飞行时间长度超过持续时间,而此时仍然没有命中目标,即视为这个弹矢无法命中目标。另外,弹矢有可能会被特殊的墙壁拦截而提前销毁。5.2.5 誓言胜利之剑技能“誓言胜利之剑”是游戏人物的绝技,拥有大范围的高额伤害效果,支持攻击力和法术强度双重加成,拥有暴击几率,在命中后还可以附加防御和恢复属性,在一定条件下减少其他技能的冷却时间,是在混战中进行击杀的强力技能。技能的介绍如图5-12所示。图5-12 主动技能“誓言胜利之剑”技能介绍这个技能的效果为在游戏人物的正前方创建从天而降的剑,在剑的运动过程中检测碰撞。当剑碰撞到了一个可攻击目标之后,就会以这个目标为中心进行范围伤害。如果在下落过程中没有碰撞,就会在短暂的延迟之后以自身为中心进行范围伤害。最终,根据技能命中的数量而额外增加加成效果。技能的效果如图5-13所示。图5-13 主动技能“誓言胜利之剑”技能效果“誓言胜利之剑”的实现分为四个部分。分别是技能使用、剑的下降、剑的碰撞检测与伤害计算、最终的加成效果。分别由四个脚本实现。技能使用模块功能为检测技能快捷键是否按下,技能本身的属性管理。这里的实现方法与上述技能相同。剑的下降效果使用的是JaveScript脚本实现的。这是因为早期技术不够全面,在模型坐标轴的操纵上不够熟练,不得不使用JavaScript脚本修正。在这里就有了JavaScript脚本和C#脚本之间的传值通信的问题。方法为强制转换和获取脚本。此外需要注意首先将JavaScript脚本放置到预编译文件夹,否则C#脚本无法获取到JavaScript脚本。不同语言脚本之间的传值示例代码如下:/JavaScript脚本var targetController1:Component= EXskiller.GetComponent(skillBasic);/指定脚本var can: FieldInfo=targetController1.GetType().GetField(canUse);/指定域var canUse =can.GetValue(targetController1);/获取值/C#脚本A jsd=(A)OBJ.GetComponent (A);jsd.XX =0;jsd.enabled=false;两种不同的语言的脚本同时会接受快捷键的检测。当快捷键按下时,由JavaScript脚本检测技能是否能使用,如果可以就创建“圣剑”,而同时由C#脚本进行属性的计算,如法力消耗,生命透支等等。剑的碰撞检测其实使用的为触发器,因此在剑与怪物碰撞时虽然触发计算但是不会阻碍剑的下降效果。这个脚本附着在被制作成预设物的“圣剑”上,出于优化考虑没有动态添加和设置。剑的伤害范围检测同样使用了相交球,进行球形范围的检测,并对范围内的目标进行攻击,其命中敌人的效果如图5-14所示。值得注意的是,这个技能在早期是使用较大范围的碰撞检测实现的,但是这需要“怪物主动撞击向剑”,显然无法实现“剑主动对身边敌人造成伤害”的效果,因此在后期改成了使用相交球检测。其中在剑的剑锷部分附有很小的碰撞器,当剑与不可穿透物体碰撞是阻碍剑继续向下运动。也因此,“誓言胜利之剑”有被格挡下来的可能。图5-14 主动技能“誓言胜利之剑”命中效果最终的加成效果的需要根据“誓言胜利之剑”命中的目标数目决定。其原理不是统一地在游戏人物身体上附加脚本,而是在被命中的目标身上增加能够修改游戏人物属性的脚本。使用初始化和销毁时调用的更新方法更新游戏人物的属性。在这里利用了游戏人物中比较重要的属性被定义为静态公有所带来的便利,这些属性将被利用与大量的脚本中。值得注意的是在削减游戏的技能冷却时间是应用到了技能的管理单元。通过检测所有非绝招并且在冷却中的技能。做如此的判定是因为没有进入冷却时期的技能如果被削减了冷却时间,那么这个增益就会缩短两次施放技能的时间,造成误差。削减冷却时间的示例代码如下:foreach (skillBasic aSkill in skills)/针对所有的主动技能if(aSkill!=skillEx.GetComponent()&!aSkill.isusing&!aSkill .canUse& aSkill .LV =1 )/满足一定条件Skill.coolTime -=aSkill.coolTimeAll *(1 - peopleMain.lengqueminus)*0.30f;/使用减法进行削减5.2.6 剑气激荡“剑气激荡”是一个辅助类型的技能。其效果为在人物造成伤害时收集剑气,可用于增强人物属性、恢复生命或强化一个主动技能,是一个辅助能力很优秀的技能。在游戏过程中可以随时消耗剑气回复生命,回复最大值为最大生命值的5%,此外在剑气低于30%时,没有恢复效果。技能介绍如图5-15所示。图5-15 技能“剑气激荡”介绍这个技能的效果可以与其他主动技能效果进行联合。其方式为在施放某一个主动技能的同时检测“剑气”是积累情况。如果剑气已满,就额外进行一些计算。并且对玩家进行文字提示。具有剑气加成的主动技能效果如图5-16所示。图5-16 具有剑气加成的主动技能效果5.3 游戏技能显示在游戏中,游戏技能是非常重要的部分,其部分属性的更新信息必须实时显示,其技能介绍不可缺少。本游戏中,技能的信息被记录在游戏技能信息面板、基本界面的技能部分和技能信息显示面板中。在游戏技能的介绍中使用的技能介绍来自于技能信息显示面板。游戏技能信息面板的内容是所有技能的技能信息显示面板内容的整合,其显示内容如图5-17所示。游戏中不乏有一些辅助性的技能,这些技能的信息被记录在游戏辅助技能信息面板中,其显示内容如图5-18所示。图5-17 游戏技能信息面板的内容图5-18 游戏辅助技能信息面板的内容此外,在游戏基本界面中对技能的状态和信息有所显示,鼠标悬停在游戏技能图表中即可获取这个游戏的技能信息。如图5-19所示。技能的状态有四种,分别是未习得、可使用、使用中和冷却中。未习得的技能的技能图标呈现灰色,且没有显示数字。可使用的技能图标呈彩色,没有显示数字。使用中的技能背景图片呈灰色,且有黄色的数字进行提示,数字内容是游戏技能剩余的持续时间,单位为秒。冷月中的技能的技能图标呈灰色,显示蓝色数字,数字内容是距离游戏技能冷却完毕剩余的时间,单位为秒。不同状态的技能图标显示内容,如图5-20所示。图5-19 游戏基本界面中对技能的显示情况图5-20 不同状态的游戏技能的图标显示内容除此之外,游戏技能的攻击范围仍然有所显示。游戏玩家可以通过鼠标悬停或者点击游戏技能图标来显示游戏技能的影响范围。技能影响范围类型有四种,分别是无范围、范围选择、范围伤害、直线伤害。不同技能的影响范围显示效果不同。对游戏技能影响范围的显示如图5-21所示。图5-21 游戏技能影响范围显示游戏技能范围的显示的原理是根据技能的类型创建不同的预设物,根据技能影响范围设定预设物的大小,最后将显示内容设置为游戏人物的子物体。当需要销毁范围显示的时候,就销毁这个预设物实例,直到下一次的显示。在游戏设计中,通过下标获取技能管理单元的技能,通过技能类型获取本身存储的对应技能显示预设物。其示例代码如下:Float areas=skillController.GetComponent().skillsthis.skillIndex.GetComponent ().skillEffectArea;/获取技能影响范围skillEffect = (GameObject)Instantiate ( skillAreaShowController.GetComponent ().choiceAreaToShow(AreaIndex),player .gameObject .transform.position,player .gameObject .transform.rotation);/创建预设skillEffect .transform.localScale = new Vector3 (areas / 3.5f, areas / 3.5f, areas / 3.5f);/改变大小skillEffect.transform .parent = player .transform; /设置父子关系5.4 游戏技能管理在游戏中,所有的主动技能都由游戏技能管理单元进行控制。限制游戏技能管理单元进行控制的因素有两个:游戏人物的死亡和游戏玩家的人工输入。而游戏技能本身的更新,由每一个技能实现。其中关键的更新为游戏技能状态更新。当技能等级大于等于1,视游戏技能已经被习得,施放技能之后将技能状态转为持续状态,持续完成之后将游戏将变为冷却状态,冷却完毕之后重新将状态更新为已习得状态。关于技能状态的更新被封装在游戏技能基类中,每一个技能仅需要在更新方法中调用即可。此外,另一个游戏技能管理的内容是游戏的升级。在游戏人物等级提升之后,玩家将获得一个普通技能的技能点,通过消耗技能点升级技能。每6级玩家获得一个绝技技能点,用于升级绝技。当没有绝技技能点而仅有技能点时,玩家无法升级绝技。在游戏中,技能升级界面显示如图5-22所示。图5-22 游戏技能升级按键显示5.5与其它模块的联系(1) 被动技能的数值更新需要参照人物属性值;(2) 一些被动技能的实现需要参照游戏进展过程中的信息记录;(3) 有些技能会对目标的自动寻路组件做相关操作;(4) 游戏装备的主动技能不受游戏主动技能控制器的影响;(5) 在没有法力的情况下可以强制使用主动技能,但会透支生命值,透支生命值有可能会使游戏人物死亡。第6章 游戏装备的设计与实现6.1装备简介游戏装备是游戏很重要的组成部分,多种多样的游戏装备组合能够塑造出丰富的游戏任务发展路线。有些装备之间的作用相辅相成,能够使游戏人物得到更大的强化。每一个装备还会有一个唯一被动技能和一个唯一主动技能,使装备能够丰富游戏人物的技能。6.1.1 装备通用属性装备与技能均有很多共同的属性用于设定,装备与技能的不同之处在于,所有的装备之间的差别在于装备的属性差异,而每一技能都是单独进行设计的,仅仅共同拥有一些属性。装备的技能脚本也是通过字符串作为参数进行绑定的。装备的通用属性介绍如下:(1) 装备名称:装备的名字;(2) 贴图名称:装备显示的贴图名称;(3) 金币数:装备的单价;(4) 装备信息:装备的介绍信息;(5) 生命上限:生命上限加成;(6) 法力上限:法力上限加成;(7) 生命恢复:生命恢复加成;(8) 法力回复:魔法恢复加成;(9) 生命偷取:生命偷取加成;(10) 法力偷取:法力偷取加成;(11) 物理攻击力:攻击力加成;(12) 法术强度:法术强度加成;(13) 物理穿透:物理穿透加成;(14) 魔法穿透:魔法穿透加成;(15) 物理反伤:物理反伤加成;(16) 魔法反伤:魔法反伤加成;(17) 物理护甲:针对攻击力的防御加成;(18) 魔法抗性:针对法术强度的防御加成;(19) 暴击率:暴击率加成;(20) 暴击额外伤害:发生暴击时的额外伤害加成(21) 闪避率:闪避率加成;(22) 格挡率:格挡率加成;(23) 格挡减免:发生格挡时伤害减免加成;(24) 冷却缩减:冷却缩减加成;(25) 生命转化:造成的物理伤害转变为自身生命的百分比加成;(26) 法术吸血:造成的魔法伤害转变为自身生命的百分比加成;(27) 攻击速度:攻击速度加成;(28) 移动速度:移动速度加成;(29) 被动:是否有被动技能;(30) 被动脚本:唯一被动脚本的名称;(31) 被动名称:被动技能的名称;(32) 被动简介:被动技能的简单介绍;(33) 被动详解:被动技能的全面介绍;(34) 主动:是否有主动技能;(35) 主动脚本:唯一主动脚本的名称;(36) 主动名称:主动技能的名称;(37) 持续时间:主动技能发动之后有效的时间;(38) 冷却时间:主动技能发动两次之间的时间间隔;(39) 主动详解:主动技能的全面介绍。6.1.2 装备技能的使用每一个装备都有一个被动技能和一个主动技能。被动技能无需玩家使用,计算机会根据技能触发的事件或条件来使用和管理这些技能,游戏人物装备上这个装备之后实时生效,例如狂徒铠甲的恢复效果,黑色切割者的穿透效果等等。主动技能是需要玩家主动施放的技能,施放这样的技能前提有二:一是玩家已经装备了这个装备;二是这一类装备的技能冷却已经完成。装备的唯一技能的唯一性在于即使游戏人物拥有多个相同的装备,这些装备的被动技能和主动技能只能够触发一层,当一件装备的主动技能冷却时,所有相同装备的主动技能也会冷却,直到冷却完毕。装备的普通加成属性则没有这层限制,可以叠加。施放装备的主动技能的快捷键是键盘的1-6键位。玩家可以通过点击不同装备对应的按键来使用相应的技能。在技能效果持续时间内,主界面上方会有技能相关的显示图标以及剩余时间的提示。装备技能的效果持续时间结束之后,装备的技能会进入到冷却时期,同时图标变为灰色。此时这个技能被封锁,无法使用,当技能冷却结束之后,装备的图标会恢复成为彩色,此时,可以使用装备技能。装备在装备栏的编号以及装备主动技能的使用如图6-1所示。图6-1 装备在装备栏的编号以及装备主动技能的使用装备技能的实现方法为动态添加脚本。当获取一件装备时,收下检查在装备栏中是否有相同的装备,只有在没有相同装备的条件下才会为游戏人物添加脚本。装备的主动技能的实现原理类似。装备主动技能在使用时,就是在游戏人物身上添加具有一定效果的脚本,而当其他相同装备在使用时,首先检查游戏人物身上是否有这个脚本,如果有,则技能无效。装备技能效果的添加示例代码如下:if (!player .gameObject.GetComponent (ComponentName) /检查时都有脚本player .gameObject .AddComponent (ComponentName);/添加脚本6.1.3 装备示例在游戏设计中,共设计了25件装备,其中24件装备能够在商店中购买得到,1件必须要使用装备合成的方法得到。所有的装备都这设置为预设物,得到装备意味着实例化一个对应装备实例。不同的装备有不同的技能实现和通用的属性。因此装备类型或基本用途之间的差异在于不同属性值之间的差异。在这里介绍两个较为典型的装备狂徒铠甲和阿塔玛之戟来展示这些装备的实现方法。这两个装备在商店中的介绍以及装备的图标如图6-2所示。图6-2 狂徒铠甲和阿塔玛之戟的图标和介绍(1) 狂徒铠甲狂徒铠甲是游戏中最强大的生命值提升装备,具有十分优秀的生命上限、法力上限、恢复效果的基本加成。其被动效果是根据最大生命值提升生命恢复。因此,其他能够提升最大生命值的装备也可以提升狂徒铠甲的被动生命恢复效果。此外,狂徒铠甲具有主动恢复生命的效果,为玩家提供“保命”方法。狂徒铠甲的被动技能的实现依赖于碰撞检测,使用碰撞检测的方法判断人物的身体是否被怪物或其他单位的武器所攻击。如果判断为被攻击,就刷新等待时间,并取消在不被攻击的情况下的生命恢复。其中,使用一个更新方法实现定时。其计算的方式为每一帧减少一定的时间,直到为负数,就会更改状态。在更新方法中做减法实现计时功能的示例代码如下:void Update () /更新方法timer -=Time .deltaTime ;/时间递减if(timer 0)/时间到timer =timerAll ;/更新计数器之后可以添加具体工作狂徒铠甲的生命恢复效果原理是改写了游戏人物生命恢复数值的公式。通过实时更新的方式修改游戏人物的生命恢复数值,从而实现生命恢复效果。也正因为如此,狂徒铠甲的生命恢复加成效果能够在人物的属性中得到。当狂徒铠甲被出售之后,因为改写生命恢复数值的脚本被销毁,游戏人物的生命恢复值被重新计算,这样就会销毁掉狂徒铠甲的效果而不修改游戏人物的本身的属性。实现公式示例代码如下:peopleMain.HPup=peopleMain.hpupLVadd*peopleMain.lv+peopleMain.hpupadd + peopleMain.Hpupstart + peopleMain .HPmax * 0.01f;/生命恢复计算公式狂徒铠甲的主动恢复效果较为简单,是一次基于最大生命值的生命恢复,使用加法实现。在游戏人物使用这个技能之后,就会在游戏人物身上生命僧名回复脚本,在生命值增加之后,一定时间之后销毁脚本。这个方法在游戏的设计与实现中被大量使用,其示例代码如下:void Start () /开始/具体工作Destroy (this.GetComponent (),Time);/一定时间后销毁(2) 阿塔玛之戟阿塔玛之戟是一个防御属性与攻击属性兼备的装备,同时对物理属性和魔法属性均有加成,但是属性加成的值不高。这个装备的灵魂在于它的唯一被动技能,护盾打击。这个技能为游戏人物提供护甲值12%的攻击力。因此,在装备这个装备后,即使全部装备护甲装备,也会获得较高的攻击力增益,使得人物能抗能打。阿塔玛之戟的被动技能同样是修改人物属性计算公式,其主动技能效果同狂徒铠甲样是一次生命的回复,在这里给出游戏人物属性修改计算公式,其余不加赘述。peopleMain.wulishuchu=peopleMain.wulishuchustart+peopleMain .wulishuchuLVadd*peopleMain.lv+peopleMain .wulishuchuadd+peopleMain .wulihujia*0.12f;/攻击力计算公式值得注意的事,很多的装备计算效果都是修改游戏人物的公式,在游戏的设计中尽可能地减少了不同计算公式带来的冲突,但是不排除拥有类似计算公式的装备带来的冲突。当具有冲突的装备被同时装备在游戏人物装备栏中时,只有最后被装备的装备的计算效果被保留。6.2装备获取与存放装备获取方式有两种,其一是在装备商店购买装备,其二是在击杀怪物的同时捡起从怪物身上掉落的装备。其中,怪物被击败后掉落装备的几率很小,能掉落的装备种类有限。6.2.1 装备获取游戏装备其实是一些图片和脚本组成的逻辑上的装备,并没有装备的模型资源。当玩家点击并且选定商店中的某一个装备之后,修改当前选定装备的数组下标,通过点击购买装备来为游戏人物添加相应的脚本,将对应的装备预设物添加引用。因此,从实现上讲,获得装备就是获得相关装备的脚本。获得装备的示例代码如下:public void ADDEquip(GameObject equip,int equipIndex)/获得装备for (int i=0; iequip.GetComponent ().gold)/金钱足够if(equipPackages i.GetComponent ().isused =false)/有空包picture= equipPackages i.GetComponentInChildren(); /找到相应的背景equipPackagesi.GetComponentInChildren().atlas=equipAtlas;/修改图集picture.spriteName =equip.GetComponent ().TextureName;/修改图片equipPackages i.GetComponent ().equip =equip;/获取装备equipPackagesi.GetComponent().equipIndex =equipIndex;/记录装备下标equipPackages i.GetComponent ().isused =true;/包已满equip.GetComponent ().add();/添加装备属性equipPackages i.GetComponent ().isequip =true;/标记为装备包而不是药物包peopleMain .gold-=equip.GetComponent ().gold;/减少金币if(equip .GetComponent ().hasskill)/如果存在被动nameADD =equip .GetComponent ().skillcomponentName;Add =true;/尝试添加脚本 break;值得注意的是,在游戏装备的脚本添加中,没有使用立即添加的方式,而是修改了是否添加的标记,从而在更新方法中进行添加。这是因为很多较为复杂的脚本难以在一帧之中添加成功,为了保证能够正确地添加脚本,将添加的方法放入更新方法中。6.2.2 装备商店装备商店用于玩家购买装备和出售装备,通过鼠标点击装备图标获取装备的信息,同时选定装备。此时就可以通过点金商店面板右侧的购买装备按钮即可尝试购买装备。当装备栏已满或者金币不够时购买失败。鼠标点击右侧的人物背包中的装备,再点击出售装备就可以卖掉对应的装备。商店面板如图6-3所示。图6-3 装备商店面板装备商店中应用到了装备预设物数组,通过数组下标进行访问。在装备商店中点击装备的图标的目的就是获取装备的下标,这些下标已经在每一个按钮中进行了设置。装备商店内的预设物数组只有一份,获取装备的实现就是调用这些装备在预设物中的加成计算方法并添加相关的脚本。装备商店的右侧有六幅图片,分别于装备栏中的六个装备栏对应,在购买装备之后,除了更新装备栏的图标,也会更新这里的图片。点击这些图片可以获取到对应的装备栏中装备的下标,如果出售装备,就会调用装备商店中预设物数组中对应下标的预设物的计算方法。6.2.3 装备栏装备栏是游戏装备的容器,是六个可以容纳装备的结构。获取装备之后,装备栏的对应位置的图片就会改变为装备图标,同时修改鼠标悬停的文字内容。因此,装备栏用于显示游戏人物的装备,而与装备本身没有关联。装备栏无法对装备进行任何操作,仅用于显示。装备栏容纳不同装备如图6-4所示。图6-4 装备栏容纳装备同时,装备栏也可以容纳药品。相同种类的多个装备需要放在不同的包中,而相同种类的药品不论多少都会放在一个包中,同时在包中显示药品的数量。这些内容在药品部分进行详细介绍。6.3装备合成在游戏中,可以通过将较低等级的装备合成获取更高级的装备。在合成的过程中,作为合成材料的装备会被销毁,同时消除这些装备的附加效果,最后为游戏人物添加新的目标装备,并添加装备附加效果。玩家可以在游戏装备合成界面选择装备合成的公式,首先根据公式获取低等级装备,在原料获取完成之后,选择公式并根据公式进行合成。如果原材料足够且合成所需要的金币数量足够,就会合成成功。而如果不满如条件,就不会合成。在装备合成界面中,玩家可以点击左下角的合成基础装备对合成公式进行筛选,通过点击向下或向上箭头选择公式。被选择的公式呈现红色,未被选择的公式呈现黑色。游戏中的装备合成界面如图6-5所示。其中,将选择的公式表现为红色,将其他的公式变现为黑色,应用了NGUI中Label富文本的特征,这一点在游戏的设计与实现中被大量应用,例如在技能的介绍中体现不同加成因素,在装备介绍中区分基本属性和装备技能属性。其动态改变Label某些文字颜色的示例代码如下:if(i=makeNowChoice)/是当前选定的公式text+=extraControls.AD(equipMakeInformationSupport)supporti).information )+n;/修改颜色,使用的是自定义的染色方法图6-5 装备合成界面装备合成的方法使用了类似购买与出售装备的方法,只是这些操作不会对金币造成影响。在装备合成之后统一进行金币的扣除。其原理可以被理解为:装备的合成时将原料免费出售,同时免费获得目标装备,最后减少需要扣除的金币。装备合成的设计中,较为灵活的一点是对装备合成公式的设计。所有装备合成公式的原料、原料数量、目标装备均可以自定义,被保存在预设物中。如果需要新建一个合成公式,只需要创建一个预设物,修改其合成原料和目标装备即可。所有的装备合成公式被管理在装备合成公式管理单元,使用数组下标的方式进行传值,选择的合成公式的过程就是改变当前选择的下标。进行合成之前会对合成条件进行判定,判定条件为原材料是否足够和是否有足够的金币。对原材料的判断是一次对游戏背包内容的遍历与判断,在这里不加以赘述。装备合成所需要的金币无法自定义,其遵循计算公式。计算公式的示例代码如下:float Allgold = (equipAim.GetComponent ().gold - gold * 0.95f) * 1.1f;/合成所需要的金币计算公式装备合成的优势在于能够使用较低等级、比较便宜的装备作为原料,制作高等级但是高价格的装备。这一点在游戏的前期是非常重要的,如果为了购买某一件昂贵的装备而在前期不购买任何装备,游戏人物将会在前期一直处于弱势。而如果玩家明确游戏人物的发展目标,则可以从小装备开始逐渐提升游戏人物的战斗属性。6.4与其它模块的联系(1) 装备的获取和出售都是针对游戏人物属性的修改,大多数装备的技能也是在一定条件下的修改;(2) 装备与药品共用装备栏,装备栏的数量固定为6个。每一件装备占用一个装备栏,每一种药品共用一个装备栏;(3) 不同装备能够提供不同属性的加成效果,配合技能所需要的加成参数选择装备能够强化技能效果;(4) 不同装备之间的效果可能会有干扰,这些干扰会影响到游戏人物的额外加成属性信息值或者这些信息值的更新,但是不会干扰到游戏人物的基础信息;在装备不同装备时需要慎重选择;(5) 在游戏中某些怪物被击杀的时候能够掉落装备,此时需要玩家鼠标左键单击装备拾起,如果此时装备栏已满则无法拾起装备。掉落的装备有生存时间,如果长时间没有拾起这件装备,装备就会自动销毁;(6) 游戏装备与游戏模型无关,任何装备都不会影响游戏人物的外观和效果。第7章 其余加成效果的设计与实现游戏中,除了技能和装备所带来的加成效果,还有很多能够产生加成效果的因素,这些因素的实现原理非常类似,都是使用了动态增加脚本组件的方法。而这些能够产生加成效果的因素又有着一些不同之处,本章将介绍这些因素的功能、应用和实现方法。7.1药品游戏中,药品是非常灵活的获取加成的方法,通过使用不同的药品,可以使游戏人物获取不同的增益效果,不同药品的效果不会相互干扰,相同药品的效果能够叠加。每一个药品都有独特的粒子效果作为显示。玩家可以在药品的界面进行购买,可以对同一种药品进行重复购买,相同的药品会累加在同一个背包之中,不会占用更多空间。游戏的药品商店界面如图7-1所示。图7-1 药品商店界面游戏玩家通过点击药品的图标获取药品的信息并选中这个药品。再选中药品之后,通过在文本框输入数字或者点击文本框左右两侧的箭头按钮即可修改一次性购买的个数,最后点击“购买药品”按钮即可尝试购买药品。如果玩家的金币数量足够,那么就会购买到所需要数目的药品,如果玩家金币不足,就会购买能够买到的最大数量的药品。购买完成之后,玩家就可以在装备栏中看到药品和药品的数量了。装备栏中显示药品和药品数量如图7-2所示。图7-2 装备栏中显示药品和药品数量获得药品之后,游戏玩家可以通过鼠标左键点击图标或者按下对应的装备栏的快捷键来使用药品。当药品生效时,在游戏基本界面上方会有图标显示,并提示出药品效果剩余时间。这种显示在游戏装备和游戏的技能中也有使用。不同药品生效时的时间提示突入7-3所示。图7-3 药品生效时在游戏基本界面上方显示的图标这种在基本界面上方显示状态的方式在游戏装备和游戏技能等等方面都有使用,是显示游戏人物身上附加的能显示出来的增益状态或者减益状态。这些用于显示的图标其实都是自带计时器的按钮,没有为其设计事件处理程序,仅仅用作显示的功能。这些按钮也被设置为预设物,当增加一个状态时,需要调用增加的方法创建预设物并修改预设物的属性。每一个预设物均有一个定时脚本,每隔一秒钟更新本身的持续时间,当持续时间为0时自我销毁,没有被调用销毁方法。因此,状态显示图标与状态之间没有调用关系,只是在创建效果的同时创建了状态显示图标,而二者又在同一时间自我销毁而已。所有的状态显示图标都被放置在一个基本显示界面上方的一个隐形的容器中,由这个容器进行排版。动态增加状态显示图标的示例代码如下:public GameObject ADDBuffButtonUseMessage(BuffshowBasic buffs)GameObject button = Instantiate(buttonProfab, transform.position, Quaternion.identity) as GameObject; /创建预设物/设置预设物各种参数return button;/将按钮传递给上一层方法以备调用游戏人物使用药品的效果不仅仅会从图标显示中体现,在游戏中,所有的药品都有不同的药品效果。当药品生效时,药品效果持续,而当药效消失,药品效果也就会随之销毁,使用被制作成预设物的粒子效果进行展示。游戏人物使用不同的药品效果如图7-4所示。图7-4 使用不同药品的时候的不同效果在药品的设计与实现中,值得注意的是药品效果的叠加的实现。在游戏中,使用的是游戏时间的叠加。例如,如果使用某一个药品,这个药品的药效持续时间为20秒,那么连续使用两个这个药品,药效的持续时间将会增加到40秒。其实现的方法是检测游戏人物身上是否有相应的药品效果脚本,如果没有就会添加脚本,而如果有,只会对已有脚本属性进行修改,而不会再一次增加脚本。其示例代码如下:if(!player.GetComponent(mediaclBuffComponnentName) )/通过名字检查是否有某药品效果脚本,如果没有就添加脚本并进行设置else/如果有就获取这个脚本,并持续时间的修改 buff=(medicalsBuffBasic)player.GetComponent(mediaclBuffComponnentName); buff.timeLast +=timeLast;/修改时间/修改其他重要参数7.2剑刃与武器剑刃与武器是附着在游戏武器上面的攻击效果,能够在普通攻击或者能够触发普通攻击特效的技能中触发使用。其原理是碰撞检测和动态添加脚本组件。通过碰撞检测来确定目标,通过动态添加脚本的方式来实现效果。剑刃与武器的不同之处在于,剑刃的效果针对不同的目标有相应的冷却时间,而武器则在到一定的时间内有有限的触发效果的次数,但是对相同的目标可以触发多次。剑刃与武器的效果能够在游戏界面中进行选择和搭配,其选择的界面如图7-5所示。图7-5 剑刃与剑的效果搭配的界面7.2.1 剑刃效果剑刃效果是通过普通攻击附加到目标怪物身上的效果,这是游戏设计中最具有灵活性的部分。剑刃效果设计简单,容易转换,能够在战斗中增加更多的可控制因素,能够配合不同的游戏人物发展路线,强化战斗,增加趣味。剑刃效果很多,在这里列举几个剑刃效果作为示例:(1) 剑刃苦痛:普通攻击使得对手中毒,每隔1.5秒造成1.25%最大生命值真实伤害,苦痛伤害最多发生三次,针对同一对手每15秒触发一次;(2) 剑刃风诀:普通攻击标记对手,消耗4%最大法力值,3秒后,被标记的对手受到这3秒内受到伤害的15%的魔法伤害,针对同一对手每20秒触发一次;(3) 剑刃夺甲:普通攻击增加已损生命值5%的护盾(最少5点),护盾值会在3秒内持续削减至最大值的55%,针对同一对手每5秒触发一次;(4) 剑刃狂热:普通攻击命中减少所有技能1秒冷却时间,消耗当前5%法力值,针对同一对手每15秒触发一次;(5) 剑刃分裂:攻击命中对目标周围50码所有对手造成攻击力10%的物理伤害,针对同一对手每7秒触发一次。不同的剑刃效果实现方式不相同,其基本的实现原理是动态添加脚本,在脚本初始化的同时造成减益效果,并定义脚本自动销毁时间,在一定时间之后销毁脚本,同时停止减益效果。当减益效果持续时间与脚本的生存时间不同时,使用计时器或者协程对时间进行操作。其中,使用协程定时产生效果的示例代码如下:IEnumerator demo()/协程入口while (条件) yield return new WaitForSeconds (timer);/执行等待时间/具体操作StartCoroutine (demo);/开启协程StopCoroutine (demo);/关闭协程为怪物目标增加剑刃效果的方式是普通攻击的命中,远程的弹矢攻击和近战攻击都会触发剑刃效果。剑刃效果的针对相同目标的冷却时间是使用脚本销毁实现的,当目标身上已经有了当前剑刃效果脚本,就不会再一次增加脚本,直到脚本销毁。为怪物添加剑刃效果的示例代码如下:void OnCollisionEnter(Collision collisioner)/碰撞检测,用于近战普攻if (collisioner.gameObject .tag = monster)/目标判断if(!collisioner .gameObject.GetComponent (EffectConNameindex) /检查脚本是否存在collisioner .gameObject .AddComponent (EffectConNameindex);/添加脚本所有的剑刃效果都被统一管理在武器上,游戏玩家可以通过改变当前选定的剑刃效果的下标改变当前选定的剑刃效果。剑刃效果的改变同样改变附着在武器上面的粒子效果的颜色,改变颜色的示例代码如下:weapon.GetComponentInChildren().startColor= colorDemo;/改变粒子系统的初始颜色7.2.2 武器效果在游戏中,游戏人物的近战普通攻击使用的是手中的刀剑,但是在游戏的设计中,游戏人物手中的武器并不是用于造成近战普通攻击基本伤害,而是用于在战斗中使用本身游戏武器的效果。游戏人物的的真正的武器是一个不可见的碰撞器,通过碰撞检测进行伤害处理。同时,游戏人物手中的武器本身也会有独有的碰撞器,用于叠加武器本身的攻击效果。游戏中的武器的装配是有条件的,就是游戏人物的等级,只有当游戏人物的等级到达武器所要求的最低等级,游戏人物能够使用不同的武器。游戏人物改变当前使用的武器,也会改变游戏人物手中的武器模型。游戏人物使用不同的武器如图7-6所示。图7-6 游戏人物使用不同的武器强力的武器会有独特的攻击效果,这些效果随着游戏人物攻击的命中触发。这些效果在一定时间内只能够触发一定的次数,在这里使用计时器来更新状态。7.3击杀增益效果在游戏中可以通过击杀相应的柱子来获得一些增益效果,这些柱子在被击杀后会在一定之间之内复活,因此可以重复击杀来获取效果。这个效果是包括游戏技能、装备、药品、武器、剑刃在内很多游戏效果添加方法的原型。游戏人物获取柱子的增益效果如图7-7所示。柱子被击杀之后会给予击杀者增益效果,同时自我毁灭,此时柱子管理单元进入相关柱子的复活等待时间,当复活时间到达,就会重新实例化一个柱子,并设置相关的参数,直到下一次柱子被击杀。图7-7 游戏人物获取击杀柱子带来的增益效果7.4与其它模块的联系(1) 增益效果增加的方式均为动态添加脚本的方式,这与装备的被动技能与主动技能脚本的添加使用的方法相同;(2) 药品与装备共享装备栏,装备栏的数量固定为6个;(3) 柱子的击杀增益效果只会在游戏主人公身上增加;(4) 柱子也是怪物的一种,但是无法移动和攻击,这是因为柱子上没有怪物AI的自动寻路组件。第8章 游戏剧情的设计与实现8.1 非战斗NPC与任务8.1.1 非战斗NPC在游戏中,游戏人物可以与非战斗NPC进行对话,很多NPC在对话之后能够为游戏人物提供一些永久的增益效果,一些特殊的NPC还可以提供任务给玩家,当玩家完成任务之后,能够给予玩家一些特别的奖励。游戏人物与NPC进行对话如图8-1所示。图8-1 游戏人物与NPC对话与NPC进行对话之后获得的增益效果只在最初的一次对话中产生,之后的对话将不再提供增益效果,与NPC的对话结果被存储在游戏存档中。这些增益的实现也是使用了动态添加脚本的方式,使用字符串对不同的脚本进行区分。与NPC的对话是游戏设计过程中非常值得注意的部分,通过与NPC对话使玩家对游戏剧情有更加深刻的了解,有助于推动游戏剧情。在对话中加入作者的思考,通过NPC将作者的想法传达给玩家,这是实现玩家与作者交流的重要的方式。虽然功能简单,但是意义重大,作为游戏不可缺少的一部分,体现着游戏真正的价值。8.1.2 游戏任务游戏中,游戏人物能够获取一些任务,通过完成任务来获取特殊的奖励。游戏中的任务分为场景核心任务和可接受任务两种。场景核心任务是必须要完成的,否则当前关卡将无法真正结束,即无法进入到下一关;可接受任务即小任务,是从NPC处得到的任务,有时间限制,超过时间限制没有完成任务就判定为任务失败。任务失败没有任何惩罚。当任务还剩余30秒就要失败时会有提示。游戏中的任务能够在游戏任务面板中看到,如图8-2所示。图8-2 游戏任务面板在游戏任务面板中,能够显示核心任务、在进行的可选任务、已完成的可选任务和未完成的可选任务。这些信息只有在任务被开启之后才会得以显示。不同状态的游戏任务的显示如图8-3所示。图8-3 不同状态的任务8.2剧情系统游戏需要较长时间的剧情播放,在剧情中需要游戏中人物的动作、移动、旋转、音频与音效的播放与切换、摄像机(视野)的移动等等诸多因素。结合这些因素,游戏应用了自制的游戏剧情系统,能够实现剧情的自动的播放。剧情系统的设计包括了每一段时间中场景中各个元素的各种变化,将这些同意在一起表现给玩家即为游戏剧情,这个游戏中的剧情长度为60秒,是使用程序制作的简单动画。游戏剧情效果参见图8-4。游戏的剧情系统实质是对游戏中资源的一个整体的管理单元,通过对不同的场景内容在相同时间做出不同的改变实现游戏剧情的前进。其示例代码如下:public void actionInPlot()/剧情推进方法if(cameraChange !=null)/摄像机移动脚本组件 cameraChange .GetComponent ().plotAction ();/接口方法/其他组件的检测和操作,都是调用实现代码的不同的接口方法图8-4 游戏剧情8.3与其它模块的联系(1) 与NPC对话带来的增益效果均为小幅度永久修改游戏人物的属性;(2) 完成游戏可选任务能够获得奖励主要为金币;(3) 场景核心任务在开启时就会给出奖励,奖励为大量的金币;NPC不具备移动能力,也不能被选定为攻击目标。第9章 游戏数据管理在游戏中,有很多的信息需要被保存到文件中,以备之后的使用,这些内容包括游戏场景存档中的大量信息记录,游戏中部分的文字内容和游戏部分内容的二进制保存结果。其中游戏的存档用于保留当前的游戏状态,当玩家读档之后即可恢复;文字内容为游戏中需要显示的较长文本;而游戏部分内容的二进制保存结果用于游戏的扩展开发。游戏数据的保存和读取是游戏中设计较为复杂的内容,使用Unity3D作为游戏引擎可以有很多种数据保存的方法,如使用数据库进行存储28、保存到XML文件中等等诸多方法。游戏的设计中曾尝试使用将必要信息写入注册表的方法,但是效果不佳,最终采用的是使用C#的文件流作为数据保存的方法。9.1游戏存档在游戏中,玩家可以随时进行存档和读档,游戏共有3个游戏存档用于保存游戏信息。这些信息都经过加密算法的处理,用于保证游戏玩家数据的安全性。9.1.1 存档与读档界面游戏的存档可以在游戏的存档面板中进行,而读档的过程可以在游戏的读档界面或者游戏的初始界面中完成。游戏中的存档和读档共有一个界面设计,如图9-1所示。图9-1 游戏存档和读档的界面通过点击相应存档的按键选择当前选定的存档,通过点击存档或读档按钮进行存档或者读档的操作。鼠标点击存档之后,能够显示出游戏存档的最后的修改时间,鼠标悬停在存档按键中能够显示出存档的截图,如图9-2所示.图9-2 鼠标悬停显示存档截图存档的选择的原理与游戏装备、药品的选择方法是一样的,都是通过点击按钮获取当前所选择的存档,并显示出一定的信息内容。其中,游戏存档的最后更新时间是存入游戏存档的时间,每一次选择一个存档,都会预先读取存档的第一行的信息,即为存档最后更新时间,然后显示在一个标签中。鼠标悬停在游戏存档按钮中显示一定内容的方法在游戏中被大量使用,即为游戏界面中的鼠标悬停显示信息的方法。在游戏设计过程中,NGUI被应用于界面的显示的主题,而GUI大量被使用于鼠标悬停信息的显示。由于主要2D界面使用了NGUI,因此需要配合NGUI的鼠标检测方法。其示例代码如下:void OnHover()/鼠标悬停或者鼠标悬停时结束if(information=true)/标记/显示一定的内容 else /停止显示一些内容void OnGUI() if(information)/检查 GUI .BeginGroup(new Rect (Screen .width /10-5,Screen .width /3-5, width+10,height+10);/GUI组,定义位置和大小 GUI .Box (new Rect (5,5, width,height), ,GUIShowStyle); /具体显示的内容 GUI .EndGroup(); /这是GUI显示方法的入口,结束GUI组存档时会对存档的场景进行截图,用于鼠标悬停时的图片显示。使用截图的方法进行截图和命名,使用动态加载资源的方法获取到图片,使用GUIStyle的背景图片的设置来设置显示的GUI图片,其示例代码如下:Application.CaptureScreenshot (+name+.png);/截图方法,引擎自带newTexture = OutResource .loadTexture (pathOfPicture);/动态加载图片资源GUIStyle GUIShowStyle=new GUIStyle();/GUI风格GUIShowStyle.normal .background = newTexture;/设置GUI的背景图片9.1.2 存档内容游戏存档的内容较为驳杂,包含游戏主人公的状态信息、游戏技能的状态信息、游戏装备信息、游戏药品信息、游戏记录信息、游戏任务信息、游戏NPC信息、游戏武器信息、游戏中音乐信息。(1) 状态信息:记录游戏人物的加成信息以及的必要的状态信息。游戏中的任务状态是根据游戏人物的加成信息和必要的计算信息通过计算公式计算得出,因此在回复游戏人物状态时只需要重新计算即可。值得注意的是,游戏人物的坐标信息也保存在存档中,当读档时因为自动寻路组件的阻碍有可能会使得游戏人物的坐标有偏差;(2) 技能状态信息:记录技能的基本状态,读档时首先将技能重置为初始状态,然后根据技能的等级重新自动升级技能。读档时的技能升级不会消耗技能点和终极技能点等资源;(3) 装备信息:记录游戏中装备栏内的装备下标。读档是通过获取下标得到相对应的装备,然后重新获取这一件装备。读档时的装备获取不消耗金币等资源;(4) 游戏记录:信息记录内容为游戏中的一些统计信息,如输出伤害、承受伤害、暴击次数、闪避次数等等。读档时根据读取的内容更新记录信息和信息在界面中的显示内容;(5) 游戏任务:记录任务的基本内容核相关属性,读档时更新装备的属性;(6) NPC信息:记录NPC与游戏人物的对话情况,设置这一项的是为了防止游戏人物重复获取NPC的永久加成增益效果;(7) 武器信息:记录游戏人物所使用的武器和剑刃效果,在读档时销毁游戏人物手中的武器并根据存档中的武器重新创建武器的预设物;(8) 音乐信息:记录当前播放的音乐,读档时切换到这个音乐。9.1.3文件存储与信息加密游戏的文件存储使用的是文件流的方法,文件存档中的每一行记录一项存档信息。游戏的存档共有3个,选择游戏存档的过程就是选择目标文件字符串的过程。游戏存档的读写过程示例代码如下:FileStream aFile = new FileStream (saves + name + dataFileEnd, FileMode.OpenOrCreate);/获取文件StreamWriter sw = new StreamWriter (aFile);/写文件sw.WriteLine (“”);/文件一行的内容sw.Close ();sw.Dispose ();/结束流FileStream aFile = new FileStream(saves+name+dataFileEnd, FileMode.OpenOrCreate ); /获取文件StreamReader sw = new StreamReader(aFile);/读文件string XXX= sw.ReadLine ();/读取一行sw.Close ();sw.Dispose ();/结束流文件中的每一行都经过了加密,加密算法是经过一点修改的DES加密方法。加密的原理是在程序提供的字符串组中随机获取一个字符串,记录这个字符串的下标,对这个下标进行一次DES加密,保存到存档文件中,之后将获取到的字符串附加到需要加密的字符串中,并整体进行一次DES加密,随后将加密的结果使用文件流写入到文件中。加密的示例代码如下:keyCoderIndex = Range (0, KeyCoder .Length);/随机字符串下标sw .WriteLine ( Encode(XXXX);/记录加密后的信息读档时,首先读取加密附加字符串的下标,通过下标获取到字符串,使用DES的解密算法解密读取到的字符串,并根据附加字符串的长度对解密后的内容进行剪切,获取到真实的字符串,最终通过强制转换将字符串转换为不同类型的值。强制转换使用了Convert类中的方法,示例代码如下:某一个值=(值类型)Convert .ToDouble ( Decode(sw.ReadLine();9.2其他文件信息在游戏中除了游戏存档还有很多地方需要读取文件,如游戏中的传奇面板中展示的文字都是通过文件动态读取的,这些文件同样进行过加密,加密方法与游戏存档的加密方法一致。9.2.1 传奇内容游戏传奇面板中的内容能够使得游戏能容更加丰满,在游戏的设计中,为每一种类的怪物和每一个武器都编写了背景故事,并在游戏的传奇面板中显示。游戏传奇面板中的传说如图9-3所示。图9-3 怪物传说和名剑传说,左侧为怪物传说右侧为名剑传说这个部分的实现较为简单,其主要的原理是通过按钮选择当前选择的文件名称,根据当前选定的文件内容读取并解密文件的字符串,最终显示到面板中。但是这个部分是游戏中需要得到更多关注的部分,这个部分承载了游戏的内涵,包含着游戏作者需要表达给游戏玩家的信息,正是这个部分使得游戏不仅仅是一个用于玩乐的工具,而有了很多的文化内容和底蕴。9.2.2 装备存储在游戏设计的过程中,将所有的装备均通过序列化的方法存储到了文件中,游戏玩家可以通过游戏装备的修改程序对装备的基本属性进行修改。使用文件保存序列化文件的示例代码如下:public static void saveSerializable(serializaer someThingToSave,string path)BinaryFormatter formatter = new BinaryFormatter ();/二进制化using (Stream output = File.Create(path) /使用文件保存formatter .Serialize(output ,someThingToSave); /序列化游戏玩家可以根据这些文件编写简单的修改程序对游戏的装备进行修改,这是游戏实现过程中保留的可修改的部分。装备修改程序示例如图9-4所示。图9-4 装备修改程序的示例9.3与其它模块的联系(1) 游戏存档中包含游戏人物的加成信息,但是没有保存能够由公式计算得出的信息;(2) 游戏存档不保存怪物的任何信息,即使怪物被击杀之后玩家存档,再次开启游戏之后读取存档,怪物仍然会刷新而不是死亡。第10章 游戏功能设置的设计与实现10.1系统设置游戏中有很多的参数可以在游戏的系统设置面板中进行设置,部分游戏设置可以通过快捷键进行快速设置。游戏系统设置面板如图10-1所示。图10-1 系统设置面板系统设置面板中的各部分功能如下:(1) 秒刷新速率:限制每秒钟更新的帧数上限,玩家的计算机性能越好,秒刷新速度越高,但是速度过高也只是对资源的浪费,因此设置有上限;(2) 分辨率:游戏显示在屏幕上的分辨率,分辨率越高越清晰,消耗资源也越多;(3) 音乐音量:游戏背景音乐的音量;(4) 音效音量:游戏音效的音量;(5) 光照亮度:游戏中太阳光的亮度,也是游戏场景中呈现出的亮度;(6) 存档:打开存档选择界面;(7) 读档:打开读档选择界面;(8) 初始界面:回到游戏的初始界面;(9) 怪物血条悬停显示:怪物血条是否实时显示;(10) 不显示怪物信息:打开/关闭鼠标悬停时怪物的详细信息显示;(11) 小地图关闭:打开/关闭小地图;(12) 开启昼夜:打开/关闭昼夜系统;(13) 开启影子:打开/关闭影子效果,影子效果会消耗很多资源,建议在资源不足时关闭;(14) 全屏模式:全屏模式和窗口模式之间的切换;(15) 结束游戏:关闭游戏。在系统设置面板中的按钮的点击事件均为改变游戏中某些相关组件的开启、关闭或一些参数,这些参数的不同将会影响脚本中相关方法的计算结果或者属性值,从而改变游戏的系统设置。其中,秒刷新速率和分辨率的按钮组是一个字定义的单选按钮组,其内容均为三个NGUI按钮。因为分别被包含在不同的组中,因此按钮的选择结果不会影响到其他组的选择结果。10.2音频管理重构观点十分重要,简言之,其意义在于改进已经写好的软件设计29。在游戏中使用的而音频管理单元,是一个有着重构思想的脚本,这个脚本已经被应用于三个游戏的开发中,提高了开发的效率。在游戏中,游戏玩家可以通过点击左右箭头来切换背景音乐,点击上下箭头来改变背景音乐的音量;可以通过按住切换键位再点击上下箭头来改变音效效果的音量。背景音乐和音效分别被管理在两个不同的数组中,通过下标进行访问。此外,播放音效的方法被定义为静态公有方法,因此调用较为方便。音频管理脚本的优势在于调用方便,功能足够,但是也有较为致命的缺陷,那就是当背景音乐被设置得过多时,这个脚本所消耗的资源较多。10.3小地图游戏中的小地图是通过不同的摄像机所观看到的内容重叠在一起得到的,不同摄像机只能够观看到不同的场景内容,原理在于将不同的物体设置为不同的layer层中。在游戏初始化阶段,在每一个游戏单位的头顶初始化一个正常摄像机不可见,而小地图摄像机可见的球体或模型,根据不同的单位类型设置不同的颜色,其中,游戏主人公的标记为剑的模型,怪物标记为红色的球,NPC被标记为绿色的球、BUFF柱子被标记为蓝色的球。游戏小地图所显示内容如图10-2所示。图10-2 游戏小地图的显示内容其中,游戏玩家可以通过点击小地图视野右侧的加号或者减号来扩大或者缩小小地图摄像机的视野,这是针对摄像机视野的操作,在游戏的每一个摄像机中均包含类似的脚本。修改摄像机视野大小和修改摄像机的视野范围的示例代码如下:topCamera.GetComponent ().farClipPlane = height * 2;/修改小地图的视野范围float fov = Camera.main.fieldOfView;/获取当前摄像机的视野参数
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
提示  人人文库网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
关于本文
本文标题:基于Unity3D引擎的“风之幻想”角色扮演游戏设计与开发
链接地址:https://www.renrendoc.com/paper/145706887.html

官方联系方式

2:不支持迅雷下载,请使用浏览器下载   
3:不支持QQ浏览器下载,请用其他浏览器   
4:下载后的文档和图纸-无水印   
5:文档经过压缩,下载后原文更清晰   
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

网站客服QQ:2881952447     

copyright@ 2020-2025  renrendoc.com 人人文库版权所有   联系电话:400-852-1180

备案号:蜀ICP备2022000484号-2       经营许可证: 川B2-20220663       公网安备川公网安备: 51019002004831号

本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知人人文库网,我们立即给予删除!