来源:U3DC.COM
作者:<a href="https://www.u3dc.com/about">Mark</a>
UGUI是unity官方开源的一套简单易用的UI框架,虽然简单易用,但如果不注意性能方面的优化,最后也可能会做出不佳的体验效果。以下几点是通过实战项目的总结得出来的优化建议,希望对使用UGUI框架的unityer有参考意义。
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>1. 动静分离</strong></font>
跟canvas的渲染机制有关,即如果一个ui元素始终是静态的,那么画布则不会重新计算绘制,如果是动态的则不然,所以,这里建议将动态和静态的元素分开。静态的元素从属一个canvas,而需要动态变动的元素从属另一个canvas。
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>2. 消除不必要的射线检测(raycast)</strong></font>
默认情况下,canvas自带Graphic Raycaster组件,这对于交互型的UI是必须的,但如果你的UI元素并不需要交互,那么每次点击都会触发判断,这种情况下,你就可以删除Graphic Raycaster组件以减少不必要的计算处理。同样的,各种其他UI元素,如图片、文本等也有Raycast Target属性,如果不需要射线检测(触屏、点击),也可以一并关掉,减少计算量。
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>3. 避免使用Camera.main</strong></font>
unity默认创建的相机为主相机(tag 为MainCamera),即main camera,可以通过unity api : Camera.main来直接获取,本质上,它是每次通过获取tag来取得的
<pre><span class="synConstant">GameObject.FindGameObjectWithTag</span>(<span class="synConstant">“ MainCamera”</span>).GetComponent <Camera>()</pre>
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
所以,建议在awake函数中缓存一次,避免多次查找(GetComponent和Find等方法是很耗时的操作)。
<pre>Awake(){
_mainCamera = Camera.main;
<span class="synComment">//与↓相同</span>
_mainCamera = <span class="synConstant">GameObject.FindGameObjectWithTag</span>(<span class="synConstant">“ MainCamera”</span>).GetComponent <Camera>();
}</pre>
回到UGUI这边,当画布的渲染模式切换为world space时,event camera的值为none,如果不指定,它会默认指向main camera,每帧将会产生7-10次的查找操作。
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>4. 慎用布局组件</strong></font>
布局组件是非常好用的功能组件,可以非常方便的用于元素内容的快速对齐排版。尽管如此,但你要是了解它的底层操作原理,你以后使用就会慎重了。因为每个布局组件会将一个GetComponents调用添加到每个子布局元素的脏读中,从而严重降低了嵌套布局组的性能。
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
另外:unity scroll rect 的实现,也是一个Layout Group 。
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>5. 合并UI对象</strong></font>
对象被重复销毁和创建的时候,我们会考虑用对象池来优化,但是这样会产生一个新问题:UI元素被重新设置,禁用和合并,这会导致Canvas不必要地变脏。
推荐优化方法:
<pre><span class="synComment">//隐藏不再使用的内容,然后</span>
_text.gameObject.SetActive(<span class="synConstant">false</span>);
<span class="synComment">//移动画布</span>
_text.transform.SetParent(_objectPoolCanvas.transform);</pre>
下次使用的时候:
<pre><span class="synComment">//从ObjectPoolCanvas移至Canvas之后,</span>
_text.transform.SetParent(_canvas.transform);
<span class="synComment">//显示</span>
_text.GameObject.SetActive(true);</pre>
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>6. 如何隐藏画布</strong></font>
通常我们禁用一个物件,使用的gameobject.setactive(true),如果我们这样禁用画布canvas的话,会触发画布显示重建,同时还会调用ondisable和onenable,增加了计算量。
推荐方法:_canvas.enable = false;
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
<font size="4" style="line-height: 45px;" color="#c200ff"><strong>7. 使用tween库而不是animator</strong></font>
有时候,UI会配合动画来做一些效果,但是应该避免空的动画,即使动画值没变,动画却依然会弄脏元素,导致canvas不断重建。所以 UGUI中不使用没有任何变化的空闲动画.
<center><img width="600" src="http://imgtec.eetrend.com/files/2020-04/%E5%8D%9A%E5%AE%A2/100048551-94…; alt=""></center><br>
推荐方式:自己写补间动画,或者直接使用三方补间库(如dotween等)。
— 于 2020年04月01日,共写了1368个字;
本文转自:u3dc.com,作者:<a href="https://www.u3dc.com/about">Mark</a> ,转载此文目的在于传递更多信息,版权归原作者所有。
原文链接:https://www.u3dc.com/archives/3585