unity8g内存(unity内存占用特别高)「unity占用内存大不大」

  自Unity支持WebGL以来,我们开辟团队就不停致力于优化WebGL的内存斲丧。在Unity文件上已有对于WebGL内存管理的细致分析,在UniteEurope2015与UniteBoston2015两届大会上,也有专题针对WebGL举行深入的讲授。然而开辟者仍旧对这方面的内容仍旧讨论热烈,以是我们意识到应该分享更多关于这方面的内容。

  UnityWebGL和别的发布平台有何差别?

  假如开辟者从一些原来就要控制内存的平台像是PC或是WebPlayer转过来的话大概已经有个底子,应该都不会造成题目。

  假如目标是游戏机(Console)的话,内存管理相对比其他平台轻易,由于可以正确知道内存是怎样运用的。你可以很好的管理内存确保游戏美满运作。手机平台内存管理就有些复杂,由于装备种类繁多,但至少可以选择最低标准的装备,并根据市场环境略过那些标准更低的装备。

  网页就没那么轻松了,抱负状态下全部玩家(Client)都有64位欣赏器和海量存储器,但究竟总是暴虐的。起首你无法知道它们盘算机的硬件规格。然后除了他们的操纵体系和欣赏器之外,并无法取得别的信息。末了玩家大概像实行别的网页一样的方法开启你的WebGL内容。因此这是一个非常复杂的题目。

  总览

  这张图形貌的是当UnityWebGL在欣赏器实行的内存设置

  

  这张图表现在UnityHeap地区上,UnityWebGL的内容会必要分配额外的内存,这里必要明白清楚才华进一步优化来低落玩家流失率。

  从图里能看到有几个内存分配,DOM,UnityHeap,AssetData以及程序代码,程序代码一旦加载网页就会永久存在内存里,其他像是AssetBundles,WebAudio,MemoryFileSystem将会依据内容差别来分配(AssetBundle下载巨细差别,音乐的播放差别等等)

  在载入的时间,asm.js分析和编译期间也有几个欣赏器内存临时分配,这里偶然间会导致32位欣赏器出现内存不敷。

  UnityHeap

  一样平常来说,UnityHeap是包罗全部Unity特定的对象(GameObjects),组件(Components),材质(Textures)和着色器(Shaders)等等。

  在WebGL,UnityHeap的巨细必要先算好让欣赏器分配内存空间,一旦分配好之后Buffer就不能重设巨细了。

  负责分配UnityHeap的程序如下:

  buffer=newArrayBuffer(TOTAL_MEMORY);

  这段程序可以在产生的build.js里找到,并会交由欣赏器的JSVM实行。

  TOTAL_MEMORY可以从PlayerSettings里的WebGLMemorySize来指定,预设环境是256MB,实际上一个空项目只有16MB。

  然而,真的游戏项目大概必要更多,在大多数环境下会必要用到256MB或386MB,记取,设定越多内存表现越多玩家能正常实行。

  原代码/编译码的内存

  程序可以实行之前必要:

1被下载到Client

2复制到一个Textblob区块

3编译

  顾虑到上述每一个步调都必要一块内存

  1.下载暂存区是临时的,但源代码和编译码在内存里会留着直到关闭页面。

  2.下载暂存区和源代码区分配的内存巨细都是由Unity所产生的无压缩js空间。估计会必要多少空间

  1

  制作一个可发布版本

  2

  将jsgz及datagz改名为*.gz,然后用解压缩的工具解开它们。

unity8g内存(unity内存占用特别高) unity8g内存(unity内存占用特别

高)「unity占用内存大不大」 行业资讯

  3

  解开后的巨细会是必要的欣赏器内存巨细

  3.编译码的巨细取决于差别欣赏器

  一个简单的优化方法是启用引擎剥离功能(StripEngineCode),那样的话发布的包就不会包罗不必要的原生的引擎码,(比方:不必要2d物理模块将会被剥除)。

  请记取,例外支持(Exceptionssupport)和第三方的套件会影响你的程序巨细,话虽云云,我们知道开辟者想要在发布时做空值查抄(nullchecks)和数组查抄(Arrayboundschecks)时内存不要销超出了例外支持的范围,为此,你可以送-emit-null-checks和-enable-array-bounds-check给il2cpp,像如许:

  PlayerSettings.SetPropertyString("additionalIl2CppArgs","--emit-null-checks--enable-array-bounds-check");

  末了请记取,发布developmentbuild会产生更多程序代码的包由于它不是minified,这应该对你来说不是题目,由于末了你会发布给玩家的是终极版本(releasebuild),对吧?;-)。

  资源(AssetData)

  在其他平台上,应用程序可以永世的存取硬盘上的内容,但在网页是没有实际的文件体系以是是不大概的,因此,一旦UnityWebGL的数据(.data档案)被下载完成后,它就会存在内存里。缺点是和其他平台相比它必要额外的内存(从5.3开始.data的档案会压缩成lz4放在内存)。比方这个Profiler阐明,256mb的Unityheap会产生约40mb的.data档案。

  

  甚么是.data档案?他是Unity产生的文件组合:data.unity3d(全部的场景,有依靠关系的资源和Resources目次底下的全部东西),unity_default_resources和引擎所必要的一些小档案。

  要相识资源简直切巨细,可以在WebGL打包完后看一下TempStagingAreaData里的data.unity3d(记取,当你关闭Unity时,temp文件夹会被删除)。你也可查察传给UnityLoader.js里DataRequest的偏移植。

  newDataRequest(0,39065934,0,0).open('GET','/data.unity3d');

  (这段程序代码大概会依照差别的Unity版本而差别-这段从Unity5.4节录)

  内存文件体系(MemoryFileSystem)

  上面提到UnityWebGL固然没有真正的文件体系,但还是可以存取数据,和其他平台相比重要的差别是在全部的I/O举动都在内存内里完成。紧张的是这个文件体系并不在Unityheap内里,因此会必要额外的内存开销,比如当我们写一个数组到档案时:

  varbuffer=newbyte[10*1014*1024];

  File.WriteAllBytes(Application.temporaryCachePath+"/buffer.bytes",buffer);

  这个档案会写到内存里,你也可以在欣赏器的profiler找到:

  

  这段Unityheap的内存是256mb

  同理,由于Unity的快取体系(cachingsystem)依靠着文件体系,整个快取也是放在如许的文件体系,这代表像PlayerPrefs和快取的AssetBundle会同样永久放在内存里直到关闭,而且是在Unityheap区的规画之外。

  AssetBundles

  低落WebGL内存斲丧最好的方法之一就是采取AssetBundle(假如你对这个不熟可以参考文件)。然而,差别的AssetBundle利用方式大概会对内存(Unityheap内或外)产生庞大的影响,有大概会造成无法再32位欣赏器无法正常实行。

  如今你必要用到AssetBundle,然后你该怎么做?将全部的资源打包成一包AssetBundle?

  千万不要!就算如许能低落网页的加载时间,你还是必要下载(大概超大)这个AssetBundle,导致内存飙高。来看看下载AB之前的内存用量:

  

  如你看到的,256mb被Unityheap界说了。这是下载了AB之后还没有放入暂存。

  

  你如今看到的是一个额外的缓冲区,约莫是同便是硬盘上的65mb,由XHR分配。这只是一个临时的缓冲区但是他大概造成内存几祯的尖峰,直到GC(garbagecollect)采取它。

  那么怎样做可以减低这些内存尖峰?必要帮每个资源创建一个AssetBundle?很风趣的想法但不太实用。

  打包AssetBundle是没有一个规则,必要根据你项目标需求来让包装下载故意义。(比方:单机游戏可选男女主角,且游戏周期只会用到一种,那选完脚色之后可以只加载该性别的包)

  末了,记取完成之后要用AssetBundle.Unload来卸除。

  AssetBundleCaching

unity8g内存(unity内存占用特别高) unity8g内存(unity内存占用特别

高)「unity占用内存大不大」 行业资讯

  WebGL的AssetBundle外取和在其他平台一样用WWW.LoadFromCacheOrDownload,固然有一个显着的差别是这是放在内存的。在UnityWebGL里AB的快取依靠IndexedDB,被放在内存文件体系里的emen编译程序支持。

  来看看用LoadFromCacheOrDownload下载AssetBundle之前的内存抓图:

  

  如你所见,512mb被Unityheap用掉了,4mb左右其他分配。包被载入之后的图:

  额外的内存需求上升至167mb左右,这是这个AssetBundle额外必要的内存(本来是64mb压缩包)。然后下图是jsvm做完GC之后的图:

  结果很多多少了,但仍必要85mb左右,大多数的内存用来存放AssetBundle,这些内存就算你用unload去开释到竣事你都无法取回内存。尚有,当玩家第二次用欣赏器打开你的内容时,不管之前是否有分配过区块,这些内存又会再次被分配。

  这是来自Chrome的内存快照参考:

  

  在Unityheap之外尚有一个Assetbundle体系所必要快取相干的临时分配。坏消息是近来我们发现它比预期的大很多,我们预期会在Unity5.5beta4,5.3.6p6和5.4.1p2修复这个题目。

  假如你用更旧的Unity版本不想升级或是你的WebGL内容已经靠近发布了,可以透过编辑器脚原来设定一些属性:

  PlayerSettings.SetPropertyString("emenArgs","-sMEMFS_APPEND_TO_TYPED_ARRAYS=1",BuildTargetGroup.WebGL);

  长远来看要最小化AssetBundle高速缓存用量最好的办理方案是用WWW构造函数而不是用LoadFromCacheOrDownload()或是没有hash/version参数的UnityWebRequest.GetAssetBundle(),假如你利用新的UnityWebRequestAPI的话。

  然后在品级利用备用的快取机制,将下载的档案直接存到indexedDB里避开内存文件体系。这是我们近来开辟放在AssetStore的方案,必要的话可随意取用修改。

  AssetBundle压缩

  在Unity5.3和5.4,都是支持LZMA和LZ4压缩的,固然利用LZMA(默认值)结果会比未压缩的LZ4来的小,但用在WebGL上有几个缺点:有显着的效能题目、必要更多内存分配。以是我们比力保举用LZ4或不要压缩(实际上,LZMA压缩法在Unity5.5会被移除),为了补充这个缺口,你大概会盼望能用gzip/brotli来压缩你的资源。

  可以查察更多关于打包压缩的相干资料

  WebAudio

  UnityWebGL的音效是有别于其他平台的,这和内存会有什么关联?

  Unity将在Java上支持创建特定的AudioBuffer对象,用来更方便播放网页音效。

  由于WebAudio缓冲区存在Unityheap表面,因此无法用Unityprofiler追踪,你必要用特定的欣赏器工具来查抄内存查察有多少用在音效上。这个例子用Firefox来查询音效内存用量:

  

  思量到这些音效缓冲存放未压缩的数据,不太得当放超大型的声音文件(比方:很长的配景音乐)。以是如今你大概必要写些本身的js套件来利用audio标签,如许声音文件压缩用较少的内存。

  FAQ

  镌汰内存利用的最佳方法是什么?简单概括如下:

  1、镌汰UnityHeap的巨细

  尽大概保持“WebGLMemorySize”够小

  2、镌汰包里程序代码量

  启用StripEngineCode

  关闭非常检测(DisableExceptions)

  克制利用第三方插件

  3、镌汰数据巨细

  利用AssetBundle

  压缩材质

  是否有可以或许决定最小WebGLMemorySize的方法?

  有,最佳方案是利用内存分析器(memoryprofiler),分析内容实际所需的内存巨细,然后依据结果改变WebGLMemorySize。

  以空项目为例,内存分析器告诉我们总利用量仅为16MB(这个值大概在差别Unity版本上有所差别),这代表只须要设定WebGLMemorySize大于16MB即可。固然,内存的总利用量将会依据内容而有所差别。

  然而,假如由于某些缘故起因无法利用分析器,可以简单地通过不绝镌汰WebGLMemorySize值,直到发现你的内容真正所必要的最小内存利用量为止。

  别的值得留意的是任何不是16的倍数的值都将被主动四舍五入(实行期间)为下一个16的倍数,这是Emen编译程序所要求的。

  WebGLMemorySize(mb)设定将决定产生html中TOTAL_MEMORY(bytes)的值。

  

  在不重新打包项目标条件下要测试内存堆栈的值,发起利用编辑html的方式。一旦找到得当的值,只需在Unity项目设定中更改WebGLMemorySize即可。

  末了,记取Unity分析器将占用一些来自Unityheap的内存,以是在利用分析器时大概必要加一些WebGL内存巨细。

  实行时发生内存溢位,怎样修复?

  这要看是Unity还是欣赏器的内存溢位。错误信息会指出题目地点息争决办法,“假如你是开辟者,可以透过在WebGL设定中为项目分配更多(或更少)的内存来办理。”可以依据此来调解WebGL内存巨细。然而尚有很多可以办理内存溢位的方法。假如出现以下错误信息:

  

  除了讯息所提之外,你还可以实行镌汰程序和数据的巨细。由于当欣赏器加载网页时,它会实行为一些内容探求空余的内存,此中最紧张的是:代码,数据,Unityheap和被编译的asm.js。它们大概相称大,尤其是数据和Unityheap内存,这对32位欣赏器来说大概是题目。

  在一些例子中,只管有充足的内存,欣赏器仍加载失败,由于内存是碎片化的。这就是为什么偶然间你的内容大概在重新启动欣赏器之后,可以乐成加载的缘故起因。

  另一种环境是,当Unity内存溢位时提示以下讯息:

  

  这种环境下就必要优化你的Unity项目。

  怎样衡量内存斲丧?

  为了分析内容所利用的欣赏器内存,可以利用Firefox欣赏器的内存工具或Chrome的Heapsnapshot。但它们无法表现WebAudio内存利用环境,因此还可以透过about:memory里的方法在Firefox里拍张快照然后征采“webaudio”找到。假如必要透过Java分析内存,请实行利用window.performance.memory(只增援Chrome)。

  利用UnityProfiler丈量Unityheap内存利用。需留意您大概必要增长WebGL的内存巨细,以便可以或许利用Profiler。

  别的,我们不停致力于开辟新的工具,以便分析发布版本:利用时先包成WebGL版本,访问https://files.unity3d.com/build-report/就能利用该工具。固然这个工具在Unity5.4中可用,但请留意这还是开辟中的功能,大概随时会更改或删除。但至少如今可以利用它到达测试的目标。

  WebGLMemorySize的最小值与最大值是多少?

  16MB是最小的,最大是2032MB,然而我们通常发起保持在512MB以下。

  是否大概由于开辟目标必要分配高出2032MB的内存?

  这是一个技能上的限定:2048MB(或更多)将会超出TypeArray所用的32位整数型态的最大值,而TypeArray被用于在Java中实现Unityheap。

  为何UnityHeap巨细不可改变?

  我们不停在思量利用Emen编译程序标记ALLOW_MEMORY_GROWTH,来答应调解Heap的巨细,但如今是没这么设定,由于它会禁用一些Chrome中的优化。我们还未对这个影响做一些真正的基准查验。预计利用这个flag会导致内存题目更严峻。假如您碰到Unityheap太小,以至于无法满意所需内存的环境,这时就必要更多内存,那么欣赏器就必须分配一个更大的Heap,从旧的内里中复制统统,然后再开释旧的Heap。这么做必要同时维持新Heap和旧Heap两份内存(直到完成复制),如许必要更多的总内存。因此反而会比利用预定固定内存的方式占用更大。

  为什么32位欣赏器在64位操纵体系上会内存溢位?

  32位欣赏器实行时的内存限定是一样的,无论操纵体系是64或32位。

  结论

  末了发起利用欣赏器专用的分析工具,来分析你的UnityWebGL内容,由于Unityprofiler无法追踪超出Unityheap之外的内存分配。

  盼望这些信息对你有效。如有任何疑问请到论坛讨论。

  点击一下

  立即阅读相干好文章

VR教诲大有可为痛点在哪丨再见了面向对象的编程丨

游戏策划进阶的二三事—市场代价篇丨

怎样练习人体我有好方法丨

“零本钱”的手机MR应用开辟

......

  近期热文

  NGUI之UIGrid可循环复用可定位列表的实现

  Unity对象池-让事物具有气愤(上)

    客户评论

    我要评论