设计院系计算机工程学院_第1页
设计院系计算机工程学院_第2页
设计院系计算机工程学院_第3页
设计院系计算机工程学院_第4页
设计院系计算机工程学院_第5页
已阅读5页,还剩55页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

附录:英文技术资料翻译 随着电子产品的不断发展游戏成为了人们日常休闲的重要部分截止2016年6月,我络游戏用户规模达到3.19亿,占整体网民的55.1%,未来将人4G游戏开发的背景人们的生活节奏越来越快,空余的休闲时间越来越碎片化,单靠传统的休闲方式已经人们的休闲要求。网络的发展,网速的提升,电子设备的更新换代使得人们休闲的方式不再受场地的限制,使得电子游戏发展迅猛。一些传统方式对人数也有限制,而电子游戏不同,哪怕一个人也可以与网友一起人数的限制,还可以文化和语言的,只要熟悉游戏规则,不同文化背景不游戏的应用价值到不同文化背景和语言背景的人,拓宽交际。unity者之剑、神庙、轩辕剑、天天飞车等。其中3D的神庙游戏因其超真实的动感体验和代入感让全球1.7亿的玩家都乐在其中。由于unity的多平台支持性,许多游戏都在不同的平台推出游戏如PC、MAC、iPAD等多个平台,和移动端的Android本游戏以一个“拦住高手”的小故事为背景,玩家采用不同的塔来拦住的类型(群伤,单伤等)。游戏中消灭高手后获得的金钱用来塔(游戏开始自带部分金钱),游戏分不同关卡,通过关卡高级塔。UnityC#语言、操作系统:Windows程序语言开发引擎:Unity3D开发工具:VisualStudio图像处理工具:AdobePhotoshopUnity3DUnity是由Unity开发的一个让玩家轻松创建诸如三维游戏UnityDirector,Blendergameengine,VirtoolsTorqueGameBuilder运行Windows和MacOSX下,可发布游戏至Windows、Mac、Wii、、Windowsphone8Android[1]。VisualStudio2013VisualStudio(简称VS)是微软公司的开发工具包系列产品。VSUML(IDE)等等。所写的目标代码适用于微软支持的所有平台包括WindowsWindowsWindowsCE.NETFramework.NETCompactFramework和Silverlight及WindowsPhone[2]。VisualStudio2013预览版以VisualStudio2012和后续的VisualWindows(Windows8.1)程序,同时在所有平台上支持多种设备和服务[3]。AdobePhotoshopPhotoshopADOBE刷、设计、封面制作、网页图像制作、编辑等领域。利用Photoshop可以C#语言C#CC++衍生出来的面向对象程的支持成为.NET[7]。UnityUnityApiObject、GameObject、shaderGameObjectGameObject是Unity中实体的基类,一个GameObject对象通常由多个组件组成,一般含有Transform组件。该类的实例方法主要用于获取GameObject组件和发 BrocastMessaged等。常用的基础语法如下:public ponent<T>whereT:public onent(stringtype)typepublic ponent(Typetype)typepublicvoidSendMessage(stringpublicvoidSendMessage(stringmethodName,objectpublicvoidSendMessage(stringmethodName,SendMessageOptionsoptions);publicvoidSendMessage(stringmethodName,objectvalue,SendMessageOptionsoptions);RigidbodyOnFixedUpdate()方法中。其中涉及的重要的实例属性如下:collisionDetectionModedragdrag>0inertiaTensormassvelocityTimeTimeUnitytime(程序运行时间)属性。常用的语法如下:publicstaticfloatrealtimeSinceStartup{ publicstaticfloatsmoothDeltaTime{ publicstaticfloattime{get;Vector2类在Unity中用于二维向量或二维点坐标的结构体类型,其中,方法、MoveTowardsScalepublicvoidpublicstaticfloatAngle(Vector2from,Vector2to)topublicstaticVector2ClampMagnitude(Vector2vector,floatpublicstaticVector2Lerp(Vector2from,Vector2to,floatt);publicstaticVector2MoveTowards(Vector2current,Vector2floatmaxDistanceDelta)currentmaxDistanceDeltapublicstaticVector2Scale(Vector2a,Vector2b)a、游戏动画游戏开发基础STG(射击游戏)是动作游戏的一种。以、等射击射击目标敌人为游戏,敌人《魂斗罗》、《》等FTG(格斗游戏)《快打》等索能力著名的类游戏《神秘岛《古墓丽影《《schoolSIM或SLG(模拟游戏)操作手术等。著名的模拟类的游戏有《模拟农场》、《外科模拟》、《城市:地平线》等。行动指令来控制角色剧情。著名的角色扮演类游戏有《勇者斗恶龙》、《最终幻想》、《塞尔达》等。所有成功游戏的主要要素就是游戏的图形声音多设计、游戏平衡性设计、ACT:ActionGame,STG:ShootingGameShootergame,射击游戏;FTG:FightingGame,格斗游戏;:全称NonyerCharacter,即“非玩家控制角色;AVG:全称AdventureGame,游戏;RPG:全称Role-yinggame,角色扮演游戏;SIMSLG:SimulationGame,模拟游戏;AI:全称ArtificialInligence,即人工智能。本游戏是一款单屏幕操作的塔防类游戏支持Windows7Windows8、Windows10等操作系统的PC机,支持分辨率为1600*900、1920*1080PC要求在满足平台需求的各PC机上运行时画面流畅声音正常操作不卡顿主要界面开始界面关卡选择界面4游戏主机界面游戏主界面由游戏场景游戏塔选择菜单和高(后文中均以指代组成。游戏场景是由5*10张草地或者柏油路方块拼接而成,场景为五行十列方块矩阵用户在场景中的地面种植塔来抵御游戏开始后沿着场景行从界面右侧匀速直线运动到左侧。界面上方有菜单,菜单显示塔的种类和价格,用户点击选择后可以点击地面种植已选择的塔,每个场景方块内只可以种植一个塔。游戏故事背景本游戏是由一个故事发展而来的创意塔防类游戏。游戏的主人公是一个行为懒散又体弱的,机缘巧合中报名参加了比赛,碍于面子必须获得比拦住中的高手,使他们至停止,使他们于主人公以达到使主人公赢面对塔也可以对塔发出,受到的塔会损失生命直至生命耗尽塔。当主游戏分关卡,每个关卡代表中的一段路程,越往后的关卡代表着游戏角色,、,,是游戏的重要组成部分有生命值值移动速度金钱值等属性只能它面前的塔,且只能一个。由AI控制,自动产生,不同关卡的数量与种类不同,高级关卡中的数量,各项属性也相对更高。停止一段时间后对主人公不会造成就会从游戏中后玩家获得自带的金钱。,、,,(2)塔也是游戏的重要部分,塔有生命值、值、价格等属性,特别的,塔可以造成群伤或者单伤。还有一些特殊的塔可以对克制一些种类的(如对某种值很高),当进入场景后塔即可。塔需要用户消耗金钱,不(2)以一定的速度超慢速前进,与任何游戏角色都不发生碰撞,但是一旦有超过游戏操作及规则用户点击菜单中的塔选择塔的种类然后点击场景中的一个方块并种植塔,每种塔都有其价格,使用金钱塔。场景中的一个方块上只能种植一个塔。当移动到场地上时塔对其发出,当移动至塔的位置时,塔,只能对当前的一个塔造成。游戏开始时系统自带一定金钱,塔消耗金钱;每种自带一定数量的钱,杀死获得金钱。塔有不同的类型,单伤群伤等;而只有单伤一种类型游戏可以选择关卡,高等级的关卡中的数量更高,且各项属性相对更高用户消灭所有的后赢得游戏,哪怕只有一个没有被消灭,都会输掉其他需求游戏的总体架构游戏场景为搭建的草地或者柏油路,由屏幕右端沿着场景行向左端作匀速直线运动,踏上游戏场景后塔可以,走到塔面前时塔。菜单标志塔的类型和价格,用户可以选择不同的塔种植,后产生不同的金钱。游戏流程图通关4-1游戏程序类设计4-24-24-3文件结构体预设、所有游戏界面、、声音等文件,其层次结构如图4-3所示。4-4游戏的开始界面由StartScene(场景)构成,开始界面中有两个主要按钮,4-5LevelScene对应相关的关卡,点击按进入相应的关卡。数字越高的关卡难度越高,用户可4-6游戏主界面是本游戏的,用户在该界面进行游戏,该界面由场地、塔、和菜单组成。主要实现的功能有塔和的彼此,金钱系统和生命系统等相机调整进入Unity界面后我们先设置主机的属性点击MainCamera在面板中设置机背景颜色为黑色,如图所示修改机的位置与尺寸4-7前期图像处理地场景基础方块的设计。最后将文件为.png

4-8游戏中的和塔均使用多张构成,有固定的游戏形象。由于作者美术平有限,故塔形象和形象均来源于网络。塔和图像的前期处理类似,所4-9PhotoshopPhotoshop):

4-10面简洁明了的原则,游戏按钮为单纯的文字,部分有简单背景。由PhotoshopPhotoshop):4-11接着选中文字,将文字的字体设置为方正舒体,大小为30点,居中,使用 4-12创建场地拼接而成,草地为前文设计的小方块。首先导入文件,即将草地4-13图层和Foreground图层,将Foreground图层置于Default图层之上,并将BackGround4-144-15在菜单点击想要的塔后点击草地,就可以在草地上创建对应的塔,同时扣除金钱。要完成这能的话,需要在草地上添加,重写OnMouseUpAsButtonInspector选项,输入Grass,再选择添加Grass。主要代码如下voidOnMouseUpAsButton()if(Build.cur!=null)Instantiate(Build.cur.gameObject,SunCollect.Score-=Build.cur.price;Build.cur=null;}}其中Build是自定义的用于菜单实例的类,变量包括创建塔的种类和游戏对象生命值会塔,塔也会 ,生命值为0时则。所以游戏对象必须拥有生命值。首先,在Scripts文件夹下创建一个名为“Health”的C#。打开后发然后在属性区域创建一个int类型的变量用来生命值,并创建一个名为doDamage的方法递减生命值,当值小于0的时候,我们删除游戏对象。这里由于不同的游戏对象的生命值不同,为了方便调试,所以将生命值变量的控制符面板中能够)代码如下intCur=publicvoiddoDamage(int{Cur-=if(Cur<={}}这段代码中,使用doDamage函数实现当前游戏物体受到减少生命值,doDamage函数中参数n表示发出的大小,根据发出的具体游戏物体具体赋值。这个将被所有有生命的游戏角色使用,包括塔和。游戏动画实现在游戏中,塔和均有动画,分为呼吸动画和动画,生成原理类似,顾一一个Unity单位,为了游戏美观和人物形象真,将的格式设置为真彩色。图Inspector图4-16动画帧设置图,将分割:图4-17动画帧分割这样就被裁切成了以帧为分界的图像。然后选择裁切好的呼吸动画,按住CTRLUnity.anim文件和一个以.controller为后缀的控制文件,对动画也做此操作。新建一个Animation文件夹用于动画,并将生成的所有动画相关的文件拖入文件夹,方用于控制动画的各项参数。双击.controller文件后在Inspector面板中修改speed参数即可修改动画的速度。此时只能看到一个动画,进行以下操作即可将两个动画动态关联。首先删除动画的控制文件,然后打开呼吸动画的控制文件并将动画的动画文件拖进当前窗口。4-18动画的Inspector为了将两个动画关联起来,可以使用Animation(动画状态机)窗口将两个动4-194-20ExitTime1。具体参数设置如下图:4-214.4.4塔自动生成图4-22参数设置然后将拖入场景,创建一个游戏物体。接着新建一个文件夹,重命名 Prefab4-23然后将游戏物体从层次面板中删除。由于是从屏幕右侧匀速直线左侧,所以需要匀速直线地从左侧飞向右侧,且要与碰撞造成CircleCollider2D碰撞盒和Rigidbody2D目区选择它,然后单击AddComponent->Physics2D选择添加一个CircleCollider2DRigidbody2D4-24CircleCollider2DRigidbody2D但会出发碰撞,响应碰撞处理消息。为了检查碰撞,本游戏使用Unity的签和判断的方法,检查是否与碰撞,碰撞成功就降低的生命值并销。创建一个C#,将其命名为BulletDamage,然后打开编辑。由于不需要TagaddTagEnemy后为游戏物体选择新建的Enemy。BulletDamage实现代码如下voidOnTriggerEnter2D(Collider2Dco)//if(co.tag=="Enemy")}}本项目使用ponent方法获取的生命值组件然后通过调用都Damage函数实现对造成,随后通过Destroy销毁游戏中的。最后将添到的克隆体原型。点击Inspector面板中的AddComponent按钮,输入BulletDamage后选择该。有了以后,由于发射出去后会匀速直线向屏幕右侧移动,所以需要在上添加移动的,新建C#文件,命名为DefaultVelocity,其代publicVector2velocity;voidFixedUpdate(){ponent<Rigidbody2D>().velocity=}设置完毕后,需要创建一个实现塔对的,在踏入场景的时刻塔才会发出。所以新建一个,命名为Firing选择C#作为其语言,将它移动到文件夹,然后打开并编辑它。由于从游戏场景右侧进入,所以本游戏可以使用RaycastAll函数,向塔右端发出射线,如果碰撞到为的物体就发出,实现代码如下publicGameObjectpublicfloatinterval=privateVector3beauty=newVector3(0.5f,0.16f,voidStart()InvokeRepeating("Shoot",0,interval);}void{if{Instantiate(bulletPrefab,transform.position+beauty,}

boolzombieInFront()Vector2origin=newVector2(9.5f,transform.position.y);RaycastHit2D[]hits=Physics2D.RaycastAll(origin,-Vector2.right); 被foreach(RaycastHit2Dhitinhits)if(hit.collider!=null&&hit.collider.gameObject.tagreturn}return}以从游戏屏幕右侧发射,但是这种方式更有意义,由于游戏过程中会出现走以后在后方种植塔,按游戏规则此时后方的塔是无法的,这样计就避免了后方的塔的问题。保存,然后选择塔游戏实例,点击于塔的游戏物体实例上。回到Inspector面板,将预设拖至变量框中,效图4-25塔参数设置4.4.5实现首先,参考4.4.5节的创建动画过程为创建动画,并保留一个实例1.0IsFiring,动画状态机将进入游戏后就沿着场景横格从右侧向左侧进行匀速直线运动,所以在Inspector图4-26组件参数设置实例上。最后分配速度,使得它慢慢左侧:图4-27移动参数设置的类似塔的,只不过只有前进到塔面前的时候才会发出。当与塔碰撞时,它应该每隔一秒钟塔一次。在Scripts文件夹下新建,续地发出消息。由于与塔碰撞需要判断PC碰撞的物体是否为塔,以防相遇也出现碰撞的情况,所以需要为塔添加一个以后,在其Inspector面板中点击Tag属性,然后选择addTag选项,新建一个选项,命名为Tower,最后在塔实例上采用该。EnemyAttacking的主要代码如下:publicfloatlast=voidOnCollisionStay2D(Collision2Dcoll)if(coll.gameObject.tag=="Tower")//动if(Time.time-last>=1) last=Time.time;}}}该中对塔一秒产生一次,使用Time.time找出最后一次使成对塔的。图4-28生命参数设置游戏菜单创建便于管理。为了方便调用,最佳的方式是将其在每个植物的克隆体原型内。游戏菜单方便用户不同类型的塔,用户点击菜单中的塔后点击场景草地即可塔。首先创建一个BuildInfo类用于塔的种类、价格和缩略图(使用户在塔时一目了然)。塔的种类不于类中,而是通过把文件添加到相应的塔上Prefab件夹中,则自动生成塔物体的预制件。然后选择所有塔的预制件,在其InspectorAddComponentNewScript,BuildInfo,C#作为语言,并将文件移至文件夹下,然后打开编辑。BuildInfo的代码publicTexturetextrue;publicintprice;//UsethisforinitializationvoidStart(){}//UpdateiscalledonceperframevoidUpdate(){}Picture(直接拖拽PixelPerUnit32,格式为真彩色。设置如下:4-29 4-30BuildInfoOnGUI和价格。GUI在一个水平区域(带框样式)在一个水平区域(带框样式)能够同时显示。于是选择在主相机上添加实现菜单功能:首先选择主相机,然InspectorAddComponentNewScript,将其命名为Build,选择C#作为语言,然后将其移动到文件夹下,打开并编辑。由于菜单只有GUI的东西,所以可以把放置于任何游戏实体上。由于这里需要它存在,所以将它添加到当前场景的主相机上时最明智的选择。代码如下publicTexturesunImage;publicBuildInfo[]nts;voidOnGUI(){

GUILayout.Box(newforeach(BuildInfobiinnts)GUI.enabled=SunCollect.Score>=if(GUILayout.Button(newcur=}}}了实现启用禁用功能即金钱足够时才可以塔的功能本项目使用GUI.enabled。地上。其中公共静态的cur变量用于为玩家准备创建的塔,因为希望从另一个它,所以被申请为了公共静态,即cur变量属性通过采用可变Build.cur方式在项目的任何地方。当建设完成后,清除cur变量。保存后,拖拽相关的游戏图像和塔的BuildInfo类实例,最终Build的参数赋图4-31Build参数设置实例时,价格大于当前金钱数目的塔则无法。效果如下图:4-324-33塔删除铲按钮Photoshop4-34然后将导入到Assets的Picture文件夹中将的格式设置为真彩色,100Apply图4-35删除铲参数设置接着,将拖进游戏场景中,调整大小和位置。新建C#文件,命名为需要一个变量是否需要删除,避免其他时候点击塔也会将塔误删。使用OnMouseUpAsButtonpublicstaticbooldeletefalsevoidOnMouseUpAsButton(){delete=}OnMouseUpAsButtonBoxCollider2DIsTrigger4-36BoxCollider2D不仅需要在删除铲上面添加,还需要塔本身添加(为了响应鼠标单击false,防止点击多次删void{if(Shovel.delete=={Shovel.delete=false;}}4-37更是打开用户对游戏的第一扇窗。本游戏的背景音效贯穿整个游戏过程,背景音效采用自动循环音频的方式Sounds,然后将音频文件拖入,方便管理。接下来将背景音乐导入游戏场景。首先选择游戏主界面的MainCamera,然后Awake选项设置为未勾选,因为声音源需要在挂载的中主动。4-38UnityFileBuildSettings...按钮。BuildSettingAddPCMac&LinuxWindows即.exeSaveAll5-1Windows20075-2戏开发的初期有一定的,有的功能实现并不完善。因此产生BUG是很正常的,BUG游戏无法随机自动产生,只能写成固定产生;游戏进入草地时塔不;游戏动画卡顿;游戏转换场景音效问题;往斜下方运动;通过不断的开发与调试代码,终于地完成了本次毕业设计课题。完成的游本设计的最点在于开发者一开始对于UnityAPI不够熟悉所以代码优化和1)游戏中的塔和种类繁多,有不同的类型,且有一些特殊属性,有的塔对特定的值特别高,同样的也有对特塔值特高。玩家可以通过不同的塔搭配在的同时开发智力。2)游戏分关卡,玩家可以选择不同的难度,富有精神。UnityUnityAPI的能力对于程序设计的步骤也更加熟悉有了从书本中学不到的成长并且又有了将书本中的知识转化为实际应用的能力,对未来的工作有很大的帮助和提高。在这个过程中,我不仅学习到了相关的技术和理论知识,还扩宽了知识面,对游戏开发从游戏设计、界面设计、程序框架设计、开发运行调试等一整个流程都有了一定的了解。题,在此我也要向他们表示衷心的感谢。参考文献2014(9):77-Web[D].北方民族大学任翔.机关会议事务管理信息系统设计与实现[D].厦门大学李金明,李金荣.Photoshop完全[M].人民邮电郑继玲.揭阳市气象局实时监测、及决策系统的研究与设计[D].北电子魏宇迪.盐业公司报账单据管理系统分析与设计[D].云南大学王文琦.郑州综合计费查询系统的开发及应用[D].邮电大学马祥涛.信息素质教育游戏中的学习支架研究[D].华中师范大学王军峰.计算机游戏界面设计方法研究[D].:[10]范长喜 城市公园儿童游戏场地空间布局研究[D].东北林业大学出处:《Unity5GameOptimization》Chapter2.ScriptingStrategiesSincescriptingwillconsumeagreatdealofourdevelopmenttime,itwillbeenormouslybeneficialtolearnsomebestpractices.ScriptingisaverythatareveryUnityspecific,focusingonproblemsarisingfromwithintheMemoryManagement.Whetheryouhavesomespecificproblemsinmindthatyouwishtosolveoryoujustwanttolearnsometechniquesforfuturereference,thischapterwillintroduceyoutoanarrayofmethodsthatyoucanusetoimproveyourscriptingeffortsnowandinthefuture.Ineachcase,wewillexplorehowandwhytheperformanceissuearises,anexamplesituationinwhichtheproblemisoccurring,andoneormoresolutionstocombattheissue.CacheComponentAcommonmistakewhenscriptinginUnityistooverusethe method.Forexample,thefollowingscriptcodeistryingtocheckacreature’shealthvalue,andifitshealthgoesbelow0,disableaseriesofComponentstoprepareitforadeathanimation:voidTakeDamage()if( ponent>().health<0){ponent<Rigidbody>().enabled=false;ponent<Collider>().enabled=false; ponent>().enabled=false;}}Eachtimethismethodexecutes,itwillreacquirefivedifferentComponentreferences.Thisisgoodintermsofheapmemoryconsumption(inthatitdoesn’tcostany),butitisnotveryfriendlyonCPUusage.ThisisparticularlyproblematicifthemainmethodwerecalledduringUpdate().Evenifitisnot,itstillmightcoincidewithotherimportantevents,suchascreatingparticleeffects,recinganobjectwitharagdoll(thusinvokingvariousactivityinthephysicsengine),andsoon.Thiscodingstyleforverylittlebenefit.Itcostsusverylittlememoryspace(only32or64bitseachtime;Unityversion,tform,andfragmentationpermitting)tocachethesereferencesapproachwouldbetoacquirethereferencesduringinitializationandkeepthemuntiltheyareneeded: privateRigidbody_rigidbody;privateCollider ponent_aiController;privateAnimator_animator;voidAwake()ponent _rigidbody _collider _aiController _animator }voidTakeDamage()if ponent.health<0)_rigidbody.detectCollisions=_collider.enabled=_aiController.enabled=}}eachtimethey’reneeded,savingussomeCPUoverheadeachtime,attheexpenseofsomeadditionalmemoryconsumption.ObtainingComponentsusingthefastestThereareseveralvariationsofthe ponent()method,andit prudenttocallthefastestpossibleversionofthismethod.Thethreeoverloadsavailableare ponent<T>(),andponent(typeof(T)).ItturnsoutthatthefastestversiondependsonwhichversionofUnitywearerunning.InUnity4,the ponent(typeof(T))methodisthefastestoftheavailableoptionsbyareasonablemargin.Let’sprovethiswithsomesimpleintnumTests ponentusing(newCustomTimer(" ponent(string)",numTests)){for(vari=0;i<numTests;++i){test= }}using(newCustomTimer(" ponent<ComponentName>",numTests)){for(vari=0;i<numTests;++i){test }}using(newCustomTimer(" ponent(typeof(ComponentName))",numTests)){for(vari=0;i<numTests;++i){test= }}Thiscodetestseachoftheponent()overloadsamilliontimes.Thisisfarmoreteststhanwouldbesensibleforatypicalproject,butitisenoughteststoprovethepoint.HereistheresultwegetwhenthetestsAsyoucansee, ponent(typeof(T))issignificantlyfasterthanponent<T>(),whichisaroundfivetimesfasterthanponent(string).ThistestwasperformedagainstUnity4.5.5,butthebehaviorshouldbeequivalentallthewaybacktoUnityponent(string)shouldnotbeused,sinceitisnotoriouslyslowandisonlyincludedforcompleteness.TheseresultschangewhenweruntheexactsametestinUnity5.madesomeperformanceenhancementstohowSystem.TypereferencesarepassedaroundinUnity5.0,and,asaresult, eessentiallyequivalent:Asyoucansee,theponent<T>()methodisonlyatinyfractionfasterthanponent(typeof(T)),whileponent(string)isnowaround30itwasinUnity4).Multipletestswillprobablyyieldsmallvariationsinofponent()whenwe’reworkinginUnity5,andtheewillbeaboutthesame.Thereisonecaveat,however.Ifwe’rerunningUnity4,thenwestillhavecamera,andsoon.ThesepropertiesbehavelikeprecachedComponentmembervariables,whicharesignificantlyfasterthanallofthetraditionalponent()methods:intnumTests= Rigidbodytest;using(newCustomTimer("Cachedreference",{for(vari=0;i<numTests;++i){test=gameObject.rigidbody;}}NotethatthiscodeisintendedforUnity4,andwillnotcompileinUnity5duetotheremovaloftherigidbodyproperty.RunningthistestinUnity4givesusthefollowingInanefforttoreducedependenciesandimprovecodemodularizationintheengine’sbackend,UnityhasdeprecatedallofthesequickaccessorvariablesinUnity5.Onlythetransformpropertyremains.Unity4usersconsideringanupgradetoUnity5shouldknowthatupgradingwillautomaticallymodifyanyofthesepropertiestousethe However,thiswillresultinuncached ponent<T>()callsscatteredthroughoutyourcode,possiblyrequiringyoutorevisitthetechniquesintroducedintheearliersection,entitledCacheComponentThemoralofthestoryisthatifwearerunningUnity4,andtherequiredusethatversion.Ifnot,thenweshouldfavor Meanwhile,ifwe’rerunningUnity5,thenwecanfavoreitherofthetype-basedversions: ponent<T>()or RemovingemptycallbackWhenwecreatenewMonoBehaviourscriptfilesinUnity,whetherwe’reusingUnity4orUnity5,itcreatestwoboilertemethodsforus://UsethisforinitializationvoidStart(){}//UpdateiscalledonceperframevoidUpdate(){}TheUnityenginehooksintothesemethodsduringinitializationandaddsthemtoalistofmethodstocallbackatkeymoments.However,ifweleavetheseasemptydeclarationsinourcodebase,thentheywillcostusasmalloverheadwhenevertheengineinvokesthem.TheStart()methodisonlycalledwhentheGameObjectisinstantiatedforthefirsttime,whichcanbewheneverthesceneisloadedoranewGameObjectisinstantiatedfromaPrefab.Therefore,leavingtheemptyStart()declarationmaynotbeparticularlynoticeableunlessthere’salotofGameObjectsinthesceneinvokingthematstartuptime.However,italsoaddsunnecessaryoverheadtoanyGameObject.Instantiate()call,whichtypicallyhappensduringkeyevents,sotheycanpotentiallyofeventsarehappeningsimultaneously.Meanwhile,theUpdate()methodiscalledeverytimethesceneisrendered.emptyUpdate()declarations,thenwecanbewastingalotofCPUcyclescausinghavoconourframewithtwotypesofComponent,onetypewithanemptyUpdate()declaration,andanotherwithnomethodsdefined:publicclass ponent:MonoBehaviour{voidUpdate(){}}public ponent:MonoBehaviour}Herearethetestresultsfor32,768Componentsofeachtype.Ifweenableallobjectswithnostubmethodsduringruntime,thennothinginterestinghappenswithCPUusageintheProfiler.WemaynoticesomememoryconsumptionchangesandsomeslightlydifferentVSyncactivity,butnothingveryconcerning.However,assoonasweenablealltheobjectswithemptyUnitycallbackdeclarations,wewillobserveahugeincreaseinCPUusage:Thefixforthisissimple;deletetheemptydeclarations.Unitywillhavenothingtohookinto,andnothingwillbecalled.Sometimes,findingsuchbasicregularexpressions(regex),weshouldbeabletofindwhatwe’relookingforrelativelyeasily.andevenNotepad++,provideawaytoperformaregex-basedsearchonthethemethodcanvarygreatlydependingonthetoolanditsversion.ThefollowingregexsearchshouldfindanyemptyUpdate()declarationsourthroughoutthemethoddeclaration.suchasOnGUI(),OnEnable(),OnDestroy(),FixedUpdate(),andsoon.ChecktheMonoBehaviourUnityationpageforacompletelistofthesecallbacksathttp: Itmightseemunlikelythatsomeonegeneratedemptyversionsofthesecallbacksinourcodebase,butneversaynever.Forexample,ifweuseacommonbaseclassMonoBehaviourthroughoutallofourcustomcomponents,thenasingleemptycallbackdeclarationinthatbaseclasswillpermeatetheentiregame,whichcancostusdearly.BeparticularlycarefuloftheOnGUI()method,asitcanbeinvokedmultipletimeswithinthesameframeoruserinterface(UI)AvoidingtheFind()andSendMessage()methodsatTheSendMessage()methodandfamilyofGameObject.Find()methodsarenotoriouslyexpensive,andshouldbeavoidedatallcosts.TheSendMessage()methodisabout2,000timesslowerthanasimplefunctioncall,andthecostoftheFind()methodscalesverypoorlywithScenecomplexitysinceitmust tethrougheveryGameObjectintheScene.ItissometimesreasonabletocallFind()duringinitializationofaScene,suchasAwake()andStart(),onlyforobjectsthatalreadyexistsintheScene.However,usingeithermethodforinter-objectcommunicationatruntimeislikelytogenerateaverynoticeableRelyingonFind()andSendMessage()typemethodsistypicallysymptomaticofpoordesign,inexperienceinprogrammingwithC#andUnity,orjustinlazinessduringprototy.Theirusagehas esomethingofanepidemicamongbeginner-andintermediate-levelprojects,suchthatUnityfeelstheneedtokeepremindinguserstoavoidusingtheminarealgame,overandoveragainintheirationandattheirconferences.Theyonlyexistasalessprogrammer-ywaytointroducenewuserstointer-objectcommunication,andforsomespecialcaseswheretheycanbeusedinalazy,butresponsible,Tobefair,Unitytargetsawidedemographicofusers,fromindividualhobbyists,students,andthosewithdelusionsofgrandeur,tosmall,mid-sized,andlargedevelopmentteams.Thisresultsinanincrediblywiderangeofsoftwaredevelopmentability.Whenyou’restartingoutwithUnity,itcanbedifficulttofigureoutonyourownwhatyoushouldbengdifferently,especiallygivenhowtheUnityenginedoesnotadheretothedesignparadigmsofmanyothergameengines.Ithassomeforeignandquirkyconceptssurroundingscenesandprefabs,aswellasnogodclassentrypoints,noranyobviousraw-datastoragesystemstoworkwith.Let’sstartbyexaminingaworst-caseexample,whichusesbothFind()andSendMessage()methods,anddiscoversomewaystoimproveuponit.Thefollowingexamplemethodattemptstoinstantiateagivennumberofenemiesfromaprefab,andthennotifiesanEnemyManagerobjectoftheirexistence:publicvoidSpawnEnemies(intnumEnemies){for(inti=0;i<numEnemies;++i){GameObjectenemy=(GameObject)GameObject.Instantiate(_enemyPrefab,Vector3.zero,Quaternion.identity);GameObjectenemyManagerObj=GameObject.Find("EnemyManager");enemyManagerObj.SendMessage("AddEnemy",enemy,}}Puttingmethodcallsinsidealoop,whichalwaysoutputtothesameresult,isabigredflagforpoorperformance,andwhenwe’redealingwithexpensiveoftheforloopandcachetheresultinalocalvariabletobeusedwithintheaponent()call.Thisrecesaverycostlymethodwithamuchgentlervariation,achievingeffectivelythesameresult.ThisgivesusthepublicvoidSpawnEnemies(intnumEnemies)GameObjectenemyManagerObj=ponentenemyMgr for(inti=0;i<numEnemies;++i)GameObjectenemyIcon=(GameObject)GameObject.Instantiate(_enemyPrefab,Vector3.zero,Quaternion.identity);}}overlyconcernedwithloadingtime,thenwecanprobablyconsiderourselvesfinishedwithouroptimizationwork.However,weoftenneednewobjectsthatareinstantiatedatruntimetofindantoregisterwithour ponentsothatitcandowhateveritneedstodotocontroltheenemyobjectsinourScene.WewouldlikeareliableandfastwayfornewobjectstofindexistingobjectswithoutunnecessaryusageoftheFind()method,duetotheoverheadinvolved.Therearemultipleapproacheswecantaketosolvingthisproblem,eachwiththeirownbenefitsandpitfalls:StaticSingletonAssignreferencestopre-existingAglobalmessagingStaticThisapproachinvolvescreatingaclassthatisgloballyaccessibletotheentirecodebaseatanytime.Theobjectstaysalivefromthemomenttheapplicationstarts,tothemomentitisclosed.Globalmanagerclassesareoftenfrownedupon,sincethenamedoesn’tsaymuchaboutwhatit’smeanttodo,andtheycanbedifficulttodebugsincechangescanoccurfromanywhere,atanypointduringruntime.Inaddition,itisprobablytheleastrobustapproachwhenitcomestochangingorrecingitatafuturedate.Despiteallofthesedrawbacks,itisbyfartheeasiestsolutiontoimplement,andsowewillcoveritfirst.TheSingletondesignpatternisacommonwayofensuringthatwehaveaglobally-accessibleobject,andthatonlyoneinstanceeverexistsinmemory.However,thewaythatSingletonsareprimarilyused(notethequalifier)inUnityprojects,canbeeasilyrecedwithasimpleC#Staticclasswithouttheneedtoimplementprivateconstructors,andtheunnecessarypropertyaccessofinC#justtakesmorecode,andtime,toachievethesameresultasastaticAstaticclassthatfunctionsinmuchthesamewayasour isusedinthepreviousexamplecanbedefinedasfollows:usingSystem.Collections.Generic;publicstaticclassEnemyManagerstaticList<GameObject>publicstaticvoidAddEnemy(GameObjectenemy)_enemies.Add}publicstaticvoidRollCall()for(inti=0;i<_enemies.Count;++i)Debug.Log(string.Format("Enemy\"{0}\"reporting}}}bydefinition,donotallowanynonstaticinstancememberstobedefined,asthatwouldimplythatwecouldsomehowduplicatetheobject.memberdata.Astaticconstructorcanbedefinedlikeso,anditiscalledthestaticEnemyManager()_enemies=new}Thistypeofglobalclassisgenerallyconsideredtobeacleanerandeasier-to-useversionofthetypicalSingletondesignpatternintheworldofC#developme.

出处:《Unity5GameOptimization》因为化将消耗我们的大量开发时间,所以学些最佳实践将是非常有益的。是一个非常宽泛的术语,因此尝试将本章中的限制为非常具体的中讨论C#语言,.NET库和MonoFramework的细微差别和高级。况下,探讨性能问题如何和为什么出现,问题发生的示例情况,以及解决问缓存组件在Unity中编写时常见的错误是过度使用ponent()方法。例如,以以准备动画:if( ponent>().health<0){ponent<Rigidbody>().enabled=false;ponent<Collider>().enabled=false; ponent>().enabled=false;}}每次该方法执行时,它将重新获取五个不同的组件。这在堆内存消耗方面是好的(因为它不花费任何成本),CPUUpdate()期间调main要重合,如创建粒子效果,用玩偶替换一个对象(以此调用物理引擎中的各种许的情况下)缓存这些以供将来使用。所以,除非你处于内存瓶颈,一个更好的方法是在初始化期间获取,并保持直到需要它们的时候: privateRigidbody_rigidbody;privateCollider ponent_aiController;privateAnimator_animator;voidAwake()ponent _rigidbody _collider _aiController _animator }if ponent.health<0)}}以这种方式缓存组件使我们无需在每次需要使用时重新获取它们,节省了一CPU个重载 (T))Unity在Unity4中, ponentusing(newCustomTimer(" ponent(string)",numTests)){for(vari=0;i<numTests;++i){test= }}using(newCustomTimer(" ponent<ComponentName>",numTests)){for(vari=0;i<numTests;++i){test }}using(newCustomTimer(" ponent(typeof(ComponentName))",numTests)){for(vari=0;i<numTests;++i){test= }} ponent()重载了一百万次。这比典型的项目测 ponent<T>(),这比ponent(string)快五倍。这个测试是针对Unity4.5.5进行的,但是它Unity 当我们在Unity5中运行完全相同的测试时,这些结果发生变化。Unityponent<T>() ponent(typeofT))基本上相等 ponent<T>()方法只比 ponent(string)现在比替代方法慢30倍(有趣的是,它甚至变得比它在Unity4中慢)。多个测试可能会产生这些结果的小变化,但最终我们可以支持 ponent()版本,当我们在Unity5中工作,结果将是相同的。然而,这里有一个警告。如果我们运行Unity4,那么我们仍然可以各种快速存的组件成员变量,这显着快于所有传统的ponent()方法:intnumTests= Rigidbodyt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论