UNITY3D手游优化2 代码需要注意的地方

在解决资源引起的性能之后,我们着手解决代码层的问题

  UNITY3D/MONO的坑是比较多的,前期制作好代码规范,后面会少走很多弯路。

 

一、MonoC#篇

  1、不要使用foreach

  每个foreach调用,大概会分配30B左右的内存.大量的调用会触发GC

  替代方案,对于数据结构list:

    For(inti=0;i

    dosth();

对于其他非线性的数据结构:

    var etr = dii.GetEnumerator();

    while (etr.MoveNext())dosth(etr.Current);

  2、尽量使用stringbuilder替代string.并且new stringbuilder(cap) 尽量预先分配好合适大小的内存.string.format的底层实现是stringbuilder,可以使用。

  3、c#对于返回的变量,基本都是新new出来的.尽量少使用.比如

  ICollection.ToArray(),会返回一个新new的T[]对象

  ToString(),会产生string临时对象

  4、不要使用Lambda表达式.每次都会有52B的内存分配. 定义函数替代之

  5、很多数据结构 比如list/Dictionary都提供了初始分配cap大小的构造函数.根据实际的需要,优先使用这样的构造函数来初始化数据结构

  6、尽量不要使用值类型到System.Object的转换.c#俗称装箱.

类似这样的转换 System.Objectobj = (System.Object)int_i;每次都会有10B的内存分配.这样小内存的频繁调用,很容易触发GC.

如果实在是必须使用,也首先考虑使用类似于MGAME的SimpleGenericParam这样的实现替换之.

  7、不要以枚举/自定义struct作为Dictionary的key.尽量考虑用基础类型int等来替代.

他们的GetHashCode都有装箱操作,每次调用TryGetValue查找都会有内存分配.

  8、尽量减少new的次数,预分配/成员变量替代临时new变量等.

  9、尽可能避免使用LINQ。部分功能无法在某些平台上使用,会分配大量GC Alloc。而且我很讨厌LINQ的一点就是它有可能在某些情况下无法很好的进行AOT编译。比如“OrderBy”会生成内部的泛型类“OrderedEnumerable”。这在AOT编译时是无法进行的,因为它只是在OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平台上也许会报错。

  10、尽可能避免使用delegate以及lambda

 

二、UNITY引擎篇

  1、不要使用Object.name,Unity每次使用都会重新new string返回 ,同理的还有component.name

真需要的话,请缓存再用

  2、if(gameobject.tag==”player”)改为gameobject.CompareTag(”player”).前者会额外有内存分配

这里可以总结成所有的UNITY引擎返回的串都要谨慎使用(包括及不限于:gameobject.transform,gameobject.name等)

  3、对于在Update中使用的很频繁的类似属性,建议直接保存子对象而不是gameobject。如把gameobject.transform换成直接访问        transform。

  4、只读的话,用sharedMaterial替代material

  5、控制StartCoroutine的次数

开启一个Coroutine(协程),至少分配37B的内存.Coroutine类的实例 -- 21B

  6、谨慎使用GetComponent系列函数

GetComponent函数如果没有找到组件,每次调用大概会分配60KB内存.

对于子结点比较多的GameObject调用GetComponentInChildren,如果调用比较深才找到,额外分配的内存甚至会达到1M多.

要求去除所有的在每帧Update中的GetComponent操作,如果有需要用到请在缓存再用。

  7、Shader的property去取不要用名字,用Shader.PropertyToID

  8、不要有空的Update/LastUpdate之类的UNITY默认回调函数.

 

三、其他注意事项

  1、TDR协议发送和接收有大量的GC,可以引入对象池解决

  2、视口外的逻辑尽量简化.表现性逻辑可以完全不走.可以比较大的提升性能.

  3、behaviac的实现,在传递behaviac定义的值参数时,会有装箱GC.写多个重载函数替代泛型实现可解决.

  4、AI可根据不同的类型定制不同的更新频率.比如普通小怪就不需要像英雄那样更新频繁.

  5、帧同步游戏,可以把逻辑帧的更新分拆,插入到两个逻辑帧中间的渲染帧去做.

  6、UGUI的Rebuild很费.可以通过独立更新频繁的Canvas . Canvas. renderMode 修改成 RenderMode.WorldSpace来改善

  总的来说,代码层面最终GC的频率需要控制在2分钟以上一次.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值