您的位置:首页 > 移动开发 > Unity3D

unity内存优化和客户端表格读取方法内存比较

2015-07-24 20:08 429 查看
1. Resource.UnloadAsset()清理引用资源 和destroy()清理实例化资源

2.Load出来的Assets其实就是个数据源,用于生成新对象或者被引用,生成的过程可能是复制(clone)也可能是引用(指针)

当你Destroy一个实例时,只是释放那些Clone对象,并不会释放引用对象和Clone的数据源对象,Destroy并不知道是否还有别的object在引用那些对象。

等到没有任何 游戏场景物体在用这些Assets以后,这些assets就成了没有引用的游离数据块了,是UnusedAssets了,这时候就可以通过 Resources.UnloadUnusedAssets来释放,Destroy不能完成这个任
务,AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何 对象在用这些Assets了。

配个图加深理解:

--------------------------------------------------------------------------------

关于客户端读表有多种方式

1.最简单的就是xml表的读取,可以使用c#的库来读,也可以使用官方推荐的一个xml解析包来读,官方推荐当然更好,因为包含的库比较少,而且也高效,c#的xml读取会增加几m的包大小。

2.使用csv读取。这种格式存成txt格式,方便用excel编辑。相比xml来说,该方法更好,因为不需要额外的包来解析xml,只需要读取tet来解析成对应数据就行。解析自己写,很简单。但是大量text的读取
字符串解析,也会造成内存过去,和效率表现一般。

3. 使用序列化方法读取:该方法比上面2种方法 效率都高,内存占用都少,但是用法稍微复杂点。但是对于MMO的话 也许这个是较好的选择方式。用法:根据表的内容来定义序列化的结构体参数,也就是说代码定义好的key从表去读。把所有数据都存到一个prefab中。最后打包使用的是prefab的数据。就不需要解析表了。也可以存成byte文件。

该方法效率很高,内存占得也少。缺点是使用不方便,策划每加一张表,都需要程序来定义结构体。而且在后边更新表的时候,也需要重新制作prefab来更新数据。

---------------------------------------------------------

关于unity官方的内存:

1. 首先有个总内存叫Totalresercerdmemory,其次有个allocate内存,这个是游戏运行使用内存,再次有个unusedreserverdmemory,该内存是未使用的临时内存。Totalresercerdmemory=allocate+unusedreserverdmemory;一般情况下unusedreserverdmemory最好是只占总内存的很小的百分比会比较好。

但是部分算法
会极大的消耗unusedreserverdmemory内存。1 频繁的字符串连接和解析。2 频繁的调用可以返回list类型函数,像读取xml表就需要经常返回很大的table数据,这个会极大消耗总内存。这也是为什么客户端读表用序列化更好。 频繁字符型解析推荐使用stringbuilder。频繁的临时变量或者list生成,建议定义一个全局的list 每次都用该list来计算 然后返回。这样就不会创建很多临时内存。千万不要在函数内new一个list返回出来,虽然看起来还行,但是频繁调用很消耗内存。

2 其他的内存优化包括图集整理,及时释放,和对象池的使用。如果场景切换的时候 要加载大量数据的时候,可能会使临时内存增加,建议切换场景先切换到空场景,进行内存释放,释放完后再切换到目标场景。

4.System.GC.Collect(0,System.GCColletionMode.Optimized) 可以在update里边 适当时间调用这个,根据情况来释放内存。

System.GC.Collect(0,System.GCColletionMode.Forced)
在切换场景的时候 强制释放内存。

还可以在切换场景的时候调用System.GC.RemoveMemoryPressure(byte)和System.GC.AddMemoryPressure(byte),来告诉gc有多余内存需要释放,也可以在通用的读表的地方
调用,读完就释放。

------

关于用Profiler监控内存问题:Profiler.GetTotalReserverdMemory()=Profiler.GetTotalunusedReserverdMemory()+Profiler.GetTotalAllocatedMemory()

总内存=垃圾(临时)内存+实际分配内存,程序占得内存为总内存。该数据在PC上可以实时监测到内存大小,比如我们游戏是300=120+180这个水平。但是在Android设备上消耗总内存也是300M左右,但是输出的结果为110=5+100左右,和实际内存相差很大。根据我们推断,在pc上unity是完全自己管理内存,所以他知道所有内存池的分配。但是在Android上可能系统底层本身对应用分配了一个内存池,unity也有一个内存池,但是属于系统池内。unity只管理自己的内存,Android底层内存他管理不到,所以数据也不一样。Android想要获取实际内存
可能还是需要去系统获取。系统和unity内存池都有一个冗余部分。

总结:

1.切换场景释放资源和GC

2.内存总量减少,压缩分类图集。

3.碎片化减少,少用string的分割和连接,少在临时函数里new list。

4.配置表采用序列化的方式。

5.在合适的时候释放资源,比如当ui打开过多,或者隔一段时间,或者在某时刻内存过大。但是释放内存肯定会卡顿一下,所以时机要选好,比如boss开始动画,结束动画 ,在切换ui可以load一会儿的地方。为避免战斗卡顿,一定不能在战斗里边随意释放。

6.内存只能尽量减少,尽量避免碎片化,不可能完全避免
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: