Unity游戏引擎游戏开发时遇到unity 内存泄漏漏问题怎么办

深入浅出Unity内存泄漏
本文通过对内存泄漏(what)及其危害性(why)的介绍,引出在Unity环境下定位和修复内存泄漏的方法和工具(how),希望能够给想要了解这方面知识的童鞋以一点帮助。最后提出了一些避免泄漏的方法与建议。
内存泄漏及其危害
相信各位程序猿们或多或少都会听到过内存泄漏这个名词,但是对于一些新手猿来说,或许不是很了解。内存泄漏?是内存漏出来了么?和霸气侧漏一样么?让我们先来看一下wikipedia的定义:
&看了一遍冗长的定义,或许各位猿们心中就是这样
一个大写的“晕”字。让我们打一个通俗的比方来解释下这个定义。
&&&&&&&&&内存泄漏,可以通俗解释为“借银行钱不还”(看来和霸气侧漏还不太一样嘛)。在计算机的二进制世界里,操作系统就是银行;每一笔贷款,都是一次内存的申请;而你,就是一个应用程序。即你向银行贷款&=&应用程序向操作系统申请内存。当然,在计算机世界中,我们需要感谢操作系统,因为他是一个不收利息的银行,你借了多少内存,你就只需要还回多少内存。那么我们可以总结一下,内存泄漏的简单定义,就是申请了内存,却没有在该释放的时候释放。
如果你总是贷款而不还钱,那么银行里的钱就越来越少,最终导致其他人要借钱时,就无钱可借了。现实生活中,银行为了避免无钱可接,就会把总是借钱不还的人拉入黑名单,不再借他钱;而操作系统则更加凶残,他会直接“做了你”,操作系统将会直接kill掉应用程序。由此可以看出,内存泄漏的危害性与严重性,如果持续泄漏,将因内存占用过大而导致应用崩溃。当然泄漏还有其他的危害,例如内存被无用对象占用,导致接下来的内存分配需要更高的时间成本,从而造成游戏的卡顿等等。
乃伊=把他,组特==作掉,出自周立波的笑侃上海30周年海派亲口
Unity中的内存泄漏
&&&&&&&&&在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏。大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧的泄漏也是因为在代码中对资源的不合理引用引起的。
l&&代码中的泄漏&&Mono内存泄漏
熟悉Unity的猿类们应该都知道,Unity是使用基于Mono的C#(当然还有其他脚本语言,不过使用的人似乎很少,在此不做讨论)作为脚本语言,它是基于Garbage
Collection(以下简称GC)机制的内存托管语言。那么既然是内存托管了,为什么还会存在内存泄漏呢?因为GC本身并不是万能的,GC能做的是通过一定的算法找到“垃圾”,并且自动将“垃圾”占用的内存回收。那么什么是垃圾呢?
我们先来看一下wikipedia上对于GC实现的简介:
定义还是过于冗长,我们来联想一下生活中,我们一般把没有利用价值的东西,称为垃圾,也就是没有用的东西,就是垃圾。在GC的世界中,也是一样的,没有引用的东西,就是“垃圾”。因为没有引用了,就意味着对于其他任何对象而言,都认为目标对象对我已经没有利用价值了,那它就是“垃圾”了。根据GC的机制,其占用的内存就会被回收。
基于以上的知识,我们很容易就可以想到为什么在托管内存的环境下,还是会出现内存泄漏了。这就像现实生活中的宅男宅女,吃了泡面总是忘记把盒子扔到门外的垃圾箱里;从计算机的角度来说,则是,在某对象超出其作用域时,我们
“忘记”清除对该无用对象的引用了。
说到这,有的同学可能会有疑问:我每次在代码中申请的内存都非常小,少则几B,多则几十K,现在设备的内存都比较大(几百M还是有的吧),即使泄漏会产生什么大影响么?
首先,水滴石穿的典故相信大家都知道,实际代码中,并非只有显示调用new才会分配内存,很多隐式的分配是不容易被发现的,例如产生一个List来存储数据,缓存了服务器下发的一份配置,产生一个字符串等等,这些操作都会产生内存的分配。你分配几十K,他分配几十K,一会儿内存就没了。
其次,有一点需要说明的是,在Unity环境下,Mono堆内存的占用,是只会增加不会减少的。具体来说,可以将Mono堆,理解为一个内存池,每次Mono内存的申请,都会在池内进行分配;释放的时候,也是归还给池,而不会归还给操作系统。如果某次分配,发现池内内存不够了,则会对池进行扩建——向操作系统申请更多的内存扩大池以满足该次的内存分配。需要注意的是,每次对池的扩建,都是一次较大的内存分配,每次扩建,都会将池扩大6-10M左右(此处无官方数据,是观察所得)。
上图是某游戏经过Cube测试的结果,可以看到Mono堆(图中黑线)内存已经达到70M 。
由此可知,Mono内存泄漏是Unity游戏开发中需要特别重视的部分。
l&&资源中的泄漏&&Native内存泄漏
资源泄漏,顾名思义,是指将资源加载之后占有了内存,但是在资源不用之后,没有将资源卸载导致内存的无谓占用。
同样的,在讨论资源内存泄漏的原因之前,我们先来看一下Unity的资源管理与回收方式。为什么要将资源内存和代码内存分开讨论,也是因为其内存管理方式存在不同的原因。
上文中说的代码分配的内存,是通过Mono虚拟机,分配在Mono堆内存上的,其内存占用量一般较小,主要目的是程序猿在处理程序逻辑时使用;而Unity的资源,是通过Unity的C
层,分配在Native堆内存上的那部分内存。举个简单的例子,通过UnityEngine命名空间中的接口分配的内存,将会通过Unity分配在Native堆;通过System命名空间中的接口分配的内存,将会通过Mono
Runtime分配在Mono堆。
了解了分配与管理方式的区别,我们再来看看回收的方式。如上文所说,Mono内存是通过GC来回收的,而Unity也提供了一种类似的方式来回收内存。不同的是,Unity的内存回收是需要主动触发的。就好比说,我们把垃圾扔在门口的垃圾桶里,GC是每天来看一次,有垃圾就收走;而Unity则需要你打个电话给它,通知它有垃圾要回收,它才会来。主动调用的接口是
。其实GC也提供了同样的接口
用来主动触发垃圾回收,这两个接口都需要很大的计算量,我们不建议在游戏运行时时不时主动调用一番,一般来说,为了避免游戏卡顿,建议在加载环节来处理垃圾回收的操作。有一点需要说明的是,
内部本身就会调用
。Unity还提供了另外一个更加暴力的方式——
来卸载资源,但是这个接口无论资源是不是“垃圾”,都会直接删除,是一个很危险的接口,建议确定资源不使用的情况下,再调用该接口。
基于上述基础知识,我们再来看一下为什么会有资源的泄漏。首先和代码侧的泄漏一样,由于“存在该释放却没有释放的错误引用”,导致回收机制认为目标对象不是“垃圾”,以至于不能被回收,这也是最常见的一种情况。
针对资源,还有一种典型的泄漏情况。由于资源卸载是主动触发的,那么清除对资源引用的时机就显得尤为重要。现在游戏的逻辑趋于复杂化,同时如果有新成员加入项目组,也未必能够清楚地了解所有资源管理的细节,如果“在触发了资源卸载之后,才清除对资源引用”,同样也会出现内存泄漏了。
还有一种资源上的泄漏,是因为Unity的一些接口在调用时会产生一份拷贝(例如Renderer.Material参考),如果在使用上不注意的话,运行时会产生较多的资源拷贝,造成内存的无端浪费。但是此类内存拷贝一般量较少,修复起来也比较简单,这里不做大篇幅的介绍
修复内存泄漏
根据上文描述,我们知道只要在回收到来之前,将引用解开就可以避免内存泄漏了,似乎是个很简单的问题。但是由于实际项目的逻辑复杂度往往超出想象,引用关系也不是简单的一层两层(有时候往往会多达十几层,甚至数十层才连接到最终的引用对象),并且可能存在交叉引用、环状引用等复杂情况,单纯从代码review的角度,是很难正确地解开引用的。如何查找导致泄漏的引用,是修复泄漏的难点和重点,也是本文主要想介绍的部分,下面就针对如何查找引用介绍几款工具。至于时序问题,比较简单,在此不做赘述。
l&&New Memory Profiler For Unity5
Unity的MemoryProfiler一直就是一个被用户诟病的地方,对于内存的使用量,被谁使用等信息,没有很好的反映。Unity5作为最新一代的Unity产品,对于这个弱点进行了一些补强,推出了新一代的内存分析工具,较好地解决了上述问题。但是没有提供两次(或多次)内存快照的比较功能,这点比较遗憾。
注:内存快照比较是寻找内存泄漏的常用手段,将两次内存的状态截取出来,进行比较,可以清楚地发现内存的变化,寻找内存的增量与泄漏点。一般会在游戏进关前以及出关后做两次dump,其中新增的内存分配,可以视为泄漏。
由于是Unity官方的工具,网上有比较详细的使用教程,在此不加赘述,可以参考下列链接或Google:
由于Unity5普及度及稳定性还有待提升,公司内普遍还是4.x的环境,那么上述的新工具就不适用了。有的同学说,升级一个5的工程来做Memory
Profile嘛,这个当然也可以,不过Unity5对于4的兼容性不太好,升级过程中需要修改不少东西,维护两个工程也是比较麻烦的事。
那么,下面就给出两个在Unity4环境下也可以使用的泄漏追踪工具。
l&&Mono内存的放大镜——Unity Cube
Cube是公司研发部开发的,针对Unity项目的性能指标收集工具,通过Cube可以较方便地获取到游戏的各项性能指标,为性能优化提供了方向。同时Cube也是游戏性能一个很好的衡量工具。Cube的使用可联系官方同学,下载地址(我真的不是在做广告)
这里我们使用“Mono内存快照获取和对比”功能。该功能可以允许用户抓取某一时刻的Mono内存状态,并且提供不同时刻内存状态的比较,快速定位到新增的内存分配。
鉴于Cube官方已经给出了详细的使用说明,就不再赘述数据的抓取过程。这里简单聊一下如何通过Cube抓取的数据更好地追踪和解决问题。
如下图所示,假设我们已经抓取了两次数据(snapshot1&
snapshot2),并且进行比较,得到两次内存快照之间新增的分配数据。
比较之后得到如下图所示的一系列数据,总结来说,就是在某个堆栈,分配了某个类型的对象,占用xx内存。这样的数据会有成千上万条(上文所说,代码中的内存分配,是非常细碎,并且数量极多的,在这里得到了验证),并且其中有很多堆栈是重复的,因为每一次的内存分配(即使是同一处位置产生的分配),都会产生一条记录。无序的数据影响了我们对数据的处理,这里我们对数据做一些分析整理。
我们举一些简单的例子来说明处理的过程。
每一条记录,都是经过一系列的函数调用(堆栈),最终分配了一些内存,用图形化的方式表示为:
& & & & & & & & &
&让我们多加一些数据:
& &通过对图的观察,我们发现可以把上述离散的图整理成一颗树:
将所有数据都做同样的归类处理之后,可以得到一颗或多颗这样的分配树。这么做的好处是:
1、&&根据函数,可以将内存的分配做一个模块的划分,快速定位到相关的模块
2、&&可以清晰地看到每一层函数的分配总量(如A函数总共分配4096 20
4096B),可以根据占用内存的多少决定修复的优先级
将对比之后的新增项一一清理之后,就可以基本清除Mono内存的多余分配和泄漏了。
l&&顺藤摸瓜——LeakParser
因为Leak Parser只是一个引用的查找工具,它并不能像Cube一样定位泄漏(即Leak
Parser不能找到哪些资源泄漏了,而Cube可以找到那些泄漏的Mono对象),在介绍Leak
Parser以及如何用它查找资源引用之前,我们需要先了解一下如何在Unity中定位资源泄漏。
我们需要使用Unity自带的Memory
Profiler(注意不是上文说的Unity5的新Profiler,是老的残疾版Profiler)。举个简单的例子,在Unity编辑器环境下运行游戏工程,经过“大厅”页面,进入到“单局”。此时打开Unity
Profiler,切换到Memory并做一次内存采样(具体请参考,不赘述)。在采样的结果中(其中包含采样时刻内存中所有的资源),点开Assets-&Texture2D,如果其中可以看到有“大厅”UI使用的贴图(如下图),那么我们可以定义这张UI贴图,属于资源上的泄漏。
为什么说这种情况就属于资源泄漏呢,因为这张UI贴图,是在“大厅”时申请的,但是在“单局”时,它已经不被需要了,可是它还在内存中。这种在不需要的时候,却还存在的内存占用,就是上文我们定义的内存泄漏。
那么在平时项目中,我们如何找到这些泄漏的资源呢?
最直观的方法,当然也是最笨的方法,就是在每次游戏状态切换的时候,做一次内存采样,并且将内存中的资源一一点开查看,判断它是否是当前游戏状态真正需要的。这种方法最大的问题,就是耗时耗力,资源数量太多眼睛容易看花看漏。
这里介绍两种讨巧的方法:
1、通过资源名来识别。即在美术资源(如贴图、材质)命名的时候,就将其所属的游戏状态放在文件名中,如某贴图叫做BG.png,在大厅中使用,则修改为OG_BG.png(OG&=
OutGame)。这样在一坨IG(IG=InGame)资源里面,混入了一个OG,可以很容易地识别出来,也方便利用程序来识别。这么做还有一个好处,可以强化美术对资源生命周期的认识,在制作资源,特别是规划UI图集时,可以有一个指导意义。
2、通过Unity提供的接口
进行资源的Dump,可以根据需求Dump贴图、材质、模型或其他资源类型,只需要将Type作为参数传入即可。Dump成功之后我们将结果保存成一份文本文件,这样可以用BeyondCompare对多次Dump之后的结果进行比较,找到新增的资源,那么这些资源就是潜在的泄漏对象,需要重点追查。
结合上述的方法与思路,应该可以轻松找到泄漏的资源了。
此时我们再回头看一下Unity
Profiler,其实Unity提供了资源索引的查找功能,只不过该功能是以一个树形结构的文本来展示的(如下图)。上文曾提到过,Unity内部的引用关系往往是非常复杂的,可能需要通过十几甚至几十层的引用,才能找到最终的引用者,并且引用关系错综复杂,形成一张庞大的图,此时光靠展开树形结构来查找,几乎是不可能的事了。
这时候就轮到我们的Leak Parser登场了,(这回真的是做广告啦)。Leak
Parser是我们项目组的xugong同学“篡改”了Mono代码之后,Dump出资源的引用关系,并通过画图库,将引用关系图表化,以方便引用关系的查找。
简单介绍一下为什么在Mono层可以Dump出引用关系。因为每一个资源的Native对象(可以认为是Unity在C
层分配的对象),在Mono层都有一个壳对象;我们平时在C#里对对象的操作,都是在壳对象上完成的。例如Mesh.GetTriangles(),我们其实是调用了壳对象Mesh的GetTriangles接口,而实际的工作,则是GetTriangles调用Unity底层的Native对象对应的NativeGetTriangles(这名字是我瞎掰的,不是真的叫这个名字,这么写是为了方便理解)来完成的。更重要的是,我们所关注的引用关系,其实都是Mono层壳对象之间的引用关系(也可以理解为是逻辑层的引用关系,逻辑层是C#实现的,逻辑层不能跳过接口,直接引用引擎层的对象),查找引用,重点也就是关注这一部分。下图展示了一个角色(Player)对资源的引用关系。
关于如何使用Leak
Parser获取泄漏对象的引用关系图,这里不加赘述,组件里已经有使用文档。这里简单介绍一下如何使用得出的引用关系图顺藤摸瓜查找泄漏的源头。
我们来看一个比较简单的引用关系图,如下图所示,图中红色对象,表示泄漏的对象,我们可以看到在图的左下角,就是我们的目标对象,我们沿着目标的引用关系向上回溯,可以看到最终是被一个粉色对象——static的ObjPool勾住了引用,沿途的引用路径上,我们都可以看到是被哪一个变量引用。这时我们可以定位到,是pool里面一个Buffer对象没有被释放,导致其使用的material也没有被释放,产生资源泄漏。
&其实在Unity的实际项目中,大多数的泄漏,都是因为static导致的。我们在做需求的时候,因为static用起来方便,可以跨过实例的束缚,快速地保存、获取数据;但是用完了之后,就忘记顺手清空static引用了。因为static的作用域是全局,回收机制都会把它当做是“非垃圾”来对待,那么相关的对象就不会被销毁了。
&&&&&&&&&当然,上面这张图属于比较简单的引用关系,当引用关系非常复杂的时候(如左下图,其实这只是一般复杂,我们遇到的最复杂情况,需要好几个屏幕才能显示下所有的引用关系),就需要尽可能地排除无关引用关系的影响(如右下图)。当然Leak
Parser也提供了接口,可以屏蔽掉一些无关的引用不显示在图上,需要在绘图前传入作为绘图参数,在工具里有具体描述,这里不赘述。
防微杜渐,避免内存泄漏
说完了如何修复内存泄漏,我还想往下多讲一步,只要我们在平时开发的过程多做思考,防微杜渐,内存泄漏是完全可以避免的。相对于等泄漏发生了再回头来追查,平时多花点时间清理“垃圾”反而是更加高效的做法。
落地到平时的开发流程中,在这里提出几点建议,欢迎各位大牛补充:
1)&&在架构上,多添加析构的abstract接口,提醒团队成员,要注意清理自己产生的“垃圾”。
2)&&严格控制static的使用,非必要的地方禁止使用static。
3)&&强化生命周期的概念,无论是代码对象还是资源,都有它存在的生命周期,在生命周期结束后就要被释放。如果可能,需要在功能设计文档中对生命周期加以描述。
相信大家出门旅游,都有看过下图类似的标语,作为一名合格的程序猿,也应该能够处理好代码中的“垃圾”,不要让我们的游戏成为一个“垃圾场”。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。浅析游戏引擎的资源管理机制(Unity3D开发者看一眼绝对不吃亏) - 水煮鱼丸 - 推酷
浅析游戏引擎的资源管理机制(Unity3D开发者看一眼绝对不吃亏) - 水煮鱼丸
游戏中通常有大量资源,如网格、材质、纹理、动画、着色器程序和音乐等,游戏引擎作为做游戏的工具,自然要提供良好的资源管理,让游戏开发者用最简单的方式使用资源。游戏引擎的资源管理包括两大部分:离线资源管理和运行时资源管理。本文仅对前者进行简要介绍,并结合Unity3D和OGRE进行分析。
资源创作与导出
游戏中的资源由各种数字内容创作工具(DCC, digital content creation)进行创作,如:
三维模型:3ds Max,Maya等;
纹理:Photoshop等;
音乐:Sound Forge等;
………………
DCC往往支持多种导出格式,如:
3ds Max:3DS、AI、DDF、DEM、DWG、DXF(TM)、HTR、FBX、IAM、IGES、IPT、LP、LS、MTL、OBJ等;
Photoshop:PSD、TIFF、EPS、PCX、GIF、JPEG、PNG、PICT、TGA等;
………………
游戏引擎一般会支持指定DDC的部分导出格式,例如Unity3D支持3ds Max导出的FBX格式;或者针对特定资源创作工具编写导出插件,例如OGRE有多种三维建模软件的
虽然基本上所有DCC都支持多种导出格式,但是很多情况下这些格式都不适合游戏引擎,因为
导出的内容过于复杂,游戏中只用到其部分数据,而游戏往往对性能的要求比较苛刻,所以需要去除冗余数据;
许多DCC导出的格式读取比较慢,而且还有一些是封闭格式导致引擎无法读取。
因此,在DCC导出资源后,需要引擎进一步处理,将资源转换为引擎的内部格式,这种处理被称作Asset Conditioning Pipeling。使用Unity3D的童鞋应该会发现,每次导入资源的时候都要读条,就是在进行Asset Conditioning Pipeling;OGRE在这方面的支持不够完善,这部分工作由自定义的导出插件完成。
资源的“编译”与“链接”
由于导出的资源存在一些问题,需要进行一定的转换,这个转换被称作Asset Conditioning Pipeling,包括2个步骤:
资源“编译”
读取单个资源的数据,将其转换为游戏中可以直接使用的格式(使用效率最高或较高的格式),例如重新对Mesh的顶点进行排序,或使用BC5等压缩算法对纹理进行压缩。这个过程与C语言的编译有些类似,因此取名为“编译”。当然,如果导出的资源可以直接使用,那么可以跳过这一步。
资源“链接”
在游戏中,许多资源并不是单独使用的,例如三维模型,它引用的材质和纹理是单独存在的资源。在上一步中,引擎对单个资源进行“编译”,将其转换为可以直接在游戏中使用的格式;这个步骤将所有的资源进行“链接”,使得游戏在运行时可以找到每个资源所依赖的所有资源,例如三维模型可以正确的找到其需要的材质和纹理。这个过程与C语言的链接有些类似,因此取名为“链接”。当然,如果导出的资源可以直接使用,那么也可以跳过这一步。
Unity3D对这部分提供了比较完善的支持,因此只需要导出引擎所支持的标准资源,并放入Assets文件夹,引擎会对其进行“编译”和“链接”,结果就在Library文件夹中(里面乱七八糟的,虽然我们看不懂,但是Unity3D很喜欢);OGRE没有提供专门的Asset Conditioning Pipeling工具,因此所有操作都在资源的导出插件中完成,没有进行单独的“编译”和“链接”。
资源管理数据库
在资源通过Asset Conditioning Pipeline之前,引擎需要存储处理该资源的方式,一般使用metadata(元数据)来描述,例如指定某个纹理应该是以何种方式压缩。引擎通过
资源数据库来管理metadata,资源数据库既可以简单的使用XML文件进行描述,也可以使用MySQL等数据库。游戏开发者通过引擎提供的接口实现资源的重新配置,例如在Unity3D编辑器中可以修改Mesh的压缩方式,选择是否优化Mesh等。
游戏引擎的资源数据库一般要提供如下功能:
创建和删除资源;
查看和修改现有资源;
将资源移动到其他路径;
支持资源的相互引用,并且在被引用资源移动路径后,保证引用有效;
提供多种便捷的查找资源的方式。
使用Unity3D的童鞋可以发现,Unity3D提供了比较完善的资源管理的功能,使用起来比较轻松。
资源读取(运行时)
在开发过程中,所有原始资源以单个文件形式进行保存,以方便修改,但是在游戏运行读取资源的时候,为了加快读取速度,一般会将资源打包成一个或多个文件。打包的原因很简单,从硬盘中读取文件的时间中,主要由三部分组成:
硬盘寻道时间;
打开文件的时间;
读取文件的时间。
最后一项是不可能改变了,除非使用速度更快的存储介质;但是将多个文件打包成一个文件,可以缩短前面两项的时间。Unity3D在发布游戏的时候,会将资源进行打包;OGRE没有自定义打包资源的方式,一般打包为
一个或多个ZIP文件,或不打包资源
拷贝Unity3D工程的时候,一定要拷贝“Assets”、“Library”和“ProjectSettings”文件夹。资源都在“Assets”,设置都在“ProjectSettings”,“Library”是来打酱油的?非也!如果不拷贝“Library”,打开工程以后你一定会大吃一惊,之前的设置全没了?!而且场景文件里的东西也是乱成一团!结合上文,则很容易理解这种诡异的现象,明白为什么少不了这个“打酱油”的“Library”。
将资源放入“Assets”文件夹,切回Unity3D,则进入Importing Assets状态(进行Asset Conditioning Pipelining),如下图
在这个步骤中,Unity3D针对所有的资源生成metadata,并进行“编译”、“链接”,转换为游戏可以直接使用的资源。转换前的资源保存在“Assets”中,转换后的资源保存在“Library”中,所有的资源在Inspector面板中可以修改metadata的数据,如下图
“Library”文件夹
如果使用SVN等版本控制器,需要同步所有资源及其metadata。打开Edit-&Project Settings-&Editor,将Mode修改为“Meta Files”(默认“Disabled”),如下图
选择“Meta Files”
Mode修改为“Meta Files”后,回到资源文件夹,会发现每个资源都多了***.meta文件,如下图,而这些.meta文件保存了这些资源将如何被Asset Conditioning Pipeline处理。
带metadata的资源文件
现在Assets文件夹中不仅有所有的资源,而且还有对应的metadata,“Library”彻底打酱油了,此时在拷贝工程或使用SVN同步工程时才可以忽略“Library”文件夹。
在发布的游戏中,资源文件如下图所示。可以发现,Unity3D对资源进行了打包,以减少资源载入时间。
发布后的游戏资源
总的来说,从导入资源,生成metadata,“编译”、“链接”资源,再到发布游戏时打包资源,Unity3D都封装好了,以最简单的方式提供给我们使用,极大的提高了游戏开发者的工作效率。虽然可能第一次在用的时候只是感觉Unity3D用的比较简单,但它确实在背后做了很多工作,只是我们没注意而已。
OGRE在这方面的支持与Unity3D相比差距比较大,只提供了资源的导出插件;发布的游戏中,可以使用ZIP对游戏资源进行打包,未提供自定义资源打包方式。当然,总体来说,它是一个相当不错的图形引擎,最重要的一点是,它是开源的。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致如有转载,请申明:
转眼我做游戏开发已经半年多了,回顾这半年,印象最深的是当初一心想学游戏什么都阻挡不了我的决心。记得那会为了学游戏,网上找了好多资料,才确定从cocos2d入门。然后下了好多入门的电子书和视频。那会刚好是学校课程最多的一个学期。基本每天都是满课,一周晚上4天有选修。为了挤出时间学习,养成了一个习惯,吃饭的时候看一集教学视频。这个习惯持续到现在,感觉还不错。好了,不多说往事了,这里给新人们介绍一下游戏开发的经验。
1 游戏开发是什么样的
这里说的游戏开发是指客户端开发,服务器端的没接触过。
我理解的大概游戏开发过程是 策划核心玩法-确立项目(大致和软件开发的流程差不多,如果是自己做一个十几天工作量的小游戏,就没必要了)-制作demo(不知道其他人是不是从头到尾完整开发)-逐步完善-内测-公测。
谈谈具体开发分工。大致分为策划、程序、UI、原画、建模、特效、音效。还可以往细分,比如策划分为总策划、关卡策划、数值策划等。什么?你跟我说只有你一个人做游戏?那么恭喜你未来的路异常艰辛。并不是说你很难身兼所有重任,主要是因为你不在歪(mei)果(guo)。作为独立开发者,最好不要惦记着国内这块蛋糕。
2 做游戏开发需要会什么
如果你只是负责客户端程序这块,那么大概是掌握一个游戏引擎。
大致分为哪些类的知识呢?(因为我只做过2D游戏,这就是按照2D的范畴来说的)
游戏框架基本原理、图像处理API、游戏引擎的坐标系、物理引擎、动画处理API、有限状态机、一门编程语言、设计模式、数据库。
下面具体介绍一下我所学过了两款游戏引擎。
Cocos2d:这款引擎是开源的代码框架,还有cocos studio编辑器,2016年还推出了组件化的Cocos
Creator。这引擎和传统的软件开发很像,通过代码来创建场景、图层、精灵等。对于熟悉软件开发的人来说,上手应该不难。这引擎用的是c++,所以熟悉c++的学cocos2d也是比较合适。但今年cocos推出了Creator,采用的是js作为开发脚本,底层还是用的cocos2d-x那套代码。如果是用cocos2d-x直接开发的话,可能要面临以下问题:有限状态机需要自己写,物理引擎用起来比较麻烦,官方的动画编辑器不太好用,要预览游戏效果需要重新编译运行,容易导致内存泄漏等问题。不过也有相应的优点,运行效率高,灵活性强等。
Unity3d:这是一款组件化的游戏引擎,用来快速开发小游戏比较合适。采用的是c#作为主语言,当然也支持js。引擎最大的优点当然是组件化,很多东西只需要在面板上设置,不用写代码去实现,可以说省了很多事。对于创建一个场景来说,只需要菜单中点击一下保存到一个文件夹中就建好。当然这不是最大的优点,最大的有优点是,重用性得到了飞跃性的提升。对于一个脚本,只要内聚不是太松散,我们可以用很多次,而在cocos2d-x中,则需要精妙的设计才能实现。当然缺点也很明显,比如灵活性差(相对的),打包的安装包体积大,运行效率低等。
3 怎么学习效率高
从我阅片无数的经历来看,先找个简单的视频入门为好,因为有人给你讲比自己看书简单。我认为入门视频讲得好的,一般都不会把全部琐细的知识都提出来,这也符合人的认知习惯,先整体,再细节。如果一开始就告诉你当一个优秀的程序员,需要学.........此处略去几张A4纸。大部分人都会被吓跑。一开始学得简单点能让你更有信心走下去。
入门之后,要做的是先找个小项目练练手,当然项目中不可能所有知识点都照顾到,但用来熟悉常用的知识点已经够了。
当你可能轻松的写一些小项目的时候,就可以开始看书补充遗漏的基础知识。然后就是找进阶的书。进阶的视频其实也可以,但是比较少,不好找,你能找到当然学起来更轻松。当你把这些知识补充完之后,可以尝试着大一点的项目(这里略去项目管理方面的东西,作为新手,应该先学会写代码。等你自己觉得项目难以维护的时候,自然会去学习规范管理的东西啦)。
最后在这里长叹一句,阿爸终于可以从坑中“逃出生天”了。
游戏有风险,入行需谨慎。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7643次
排名:千里之外
原创:50篇
评论:16条
(2)(5)(6)(11)(8)(17)(3)}

我要回帖

更多关于 unity 内存泄漏工具 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信