Unity3d机制性问题和C#性能问题

Unity3d机制性能问题

1.减少Find,FindGameObjectWithTag,GetCompen,GetChildt等函数,特别是每帧使用,应尽可能在Awake,Start函数里查找,并缓存起来,以便多次使用。一些方法要经常获取就应该统一一个地方,一次性获取,减少后面获取的数量。

Awake在脚本被实例化的时候会被调用(不管脚本是不是enable),而且在脚本的生命周期中只会被调用一次。Awake是在所有对象实例化之后,所以可以使用诸如GameObject,Fine之类的方法来在Awake中给各个组件之间添加引用关系。Awake会在所有对象Start之前调用(跟所挂的GameObject有关)

Start是在对象第一次enable之后,在Update之前调用的,start在脚本生命周期也只可能被调用一次,start可能不会被立刻调用,因为在enable之后(跟所在的脚本有关)

2.尽量不要使用SendMessage,BroadCastMessage,SendMessageUpwards函数,特别是每帧使用,如需要应当使用Delegate替代(委托)

3.不应当每帧改变transform.localscale,这样效率会很慢

4.如果想比较两个向量长度,用sqrMagnitude会快很多。

5.当一个脚本挂在一个GameObject上面时,如不需要Update函数的时候就删除它,在创建一个新脚本的时候,系统会自动加入一个空的Update函数。

6.尽量不要使用FixedUpdate()函数,这种函数在每一个物体的每一个脚本中每秒调用50-100次,如果可以的话尽量把这个函数的东西转移到Update中执行。

7.人物身上少挂载组件,用一个组件触发其他类执行会更好。比如,创建人物移动的类,这个类不继承mono,然后用一个人物的组件(统管整个人物的组件)的update触发去触发人物移动的类的update。这样人物移动也可以做相应行为。这样可以减少人物挂载的组件。

8.少用projector的方式做投影显示。因为每个projector都会有一个相机,这样会产生很多gc。无法合并dc。用面片(quad)然后用rvocontroller可以让他贴在地面上。

9.字典的key不能用枚举,会有gc

10.当有没用到的widget时就应该要隐藏他,不然UIPanel的update会消耗比较高。

11.所有设置能跟随qualitysettings走的话就跟随qualitysettings走,这样可以一并设置显示质量

12.不再主场景就把主场景的摄像机关了,不在相关的页面则隐藏相关的页面

13.切换界面时并且时全屏界面时,不在当前界面的里面的uirect和camera组件都隐藏,因为可能有特效之类

14.显示不出来的shader中的pass(因为在ui上如果不写深度的话一些pass会在ui后面)就不要渲染,可以关闭该pass减少dc

15.rendertexture能用低质量的就用低质量的,比如用ARGB4444能显示正常的就不用全质量,能降低采样的就降低采样,因为rt一般比较可能用在摄像机的targetrendertexture里,所以本身的rt越小性能越好。而且如果只渲染纯色的话可以把rt的深度关了。

16.ngui的话层级depth如果是同一个图集的话要设置成一样的数值,并且在项目开始时就要规划好哪个图集用在哪些区间。比如LTCombatHud_Atlas是1到50,人物血条是-300到-400,label字体是490到600

17.不是因为动静分离的话,panel尽量只用一个,因为不同的panel同样的图集同样的深度也是会截断的,就会产生截断的多余的dc

18.开启多线程渲染

19.同样类型的物品如果只是颜色不一样的话就用一个白色贴图然后改颜色就可以了,这样可以合批

20.shader尽量剔除背面

21.特效总时长要跟真实的特效播放时长一致,不然本来只需要创建一个特效,因为还在显示则对象池就去创建了多个特效

22.一些比较常用的特效就不要清除了,缓存起来,比如人物出场的特效,用空间换时间。

23.在一些场景如果前一个场景不能移除则应该要隐藏起来,并且相应的逻辑上的update也要return

C#的性能问题

1.不应当在每帧中或者频繁的new对象或数组,这样会频繁的造成垃圾内存而导致过多的垃圾回收,效率比较慢,如需要可以使用对象池管理

对象池使用需要考虑的点:

(1)很多类型的对象被重新使用前,在某些情况下,需被reset。至少,所有的成员变量都要设置成初始值。这个可以在池中实现而不需要用户处理。考虑的是【1】重置是立即,还是延迟的 【2】重置是被池管理,还是声明池对象的类

(2)当池对象需要显示声明在类级别作用域,显然,如需要一个其他类型的对象池时就需要重新声明

(3)创建管理所有类型池的ObjectPool

(4)考虑池是否需要显示上限并提供一个针对分配对象失败的安全措施

(5)池中对象很多却很少使用,需要收缩

(6)池可以被多个线程共享,实现为线程安全

实际实现:

(1)重置是必须的,但不限重置到底在池中还是管理类中

(2)Unity强制限制多线程,可以在主线程中定义工作者线程,但只有主线程可以调用Unity API,一般不需要实现为支持多线程

(3)可以一个类型声明一个新的池,可选的方案,采用单例模式:创建一个新的对象池并放置于存储池的字典中,该字典放置在一个静态变量中。

 

2.多个脚本需要使用的数据,应采用static类型(或者单例)实现

3.尽量避免直接使用foreach,在momo,foreach会造成过多内存开销,可以声明一个List<>之类的方式,然后for去遍历

4.减少不必要的循环或每帧中的循环

5.在使用Dictionary的时候,尽量不要把string类型作为key,因为每次通过字符串添加和查找的时候,都会hash字符串,字符串越长,查找次数越多,效率越低。

 

物理引擎性能问题:

1.尽量不要使用MeshCollider作为碰撞体。如一定使用,也应尽可能减少网络碰撞体的面数,又或者使用Unity3d原生碰撞体,Sphere,Box,Capsule的组合来代替MeshCollider

2.CharacterController与Rigidbody+CapsuleCollider,后者在物体较多的情况下,性能高很多。

 

优化方案:

1.先在pc上用profile,找耗时的函数,最好找到对象。然后根据执行的代码优化内容。
2.特效的优化就是优先加载好再执行,用对象池包装起来。
3.尽量再该界面不会有其他界面的内容再执行,比如不会有主场景的内容再执行
4.尽量分帧执行或分帧加载内容,均到每帧来做
5.Ui的dc尽量减少
6.Mesh能静态的就做静态的
7.材质尽量共用,才能合批
8.多线程渲染的开关


 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值