1. 程式人生 > >關於 Unity 的 GetComponent 函式所產生的GC問題

關於 Unity 的 GetComponent 函式所產生的GC問題

前言:

最近的專案優化GC,其中看到關於GetComponent的GC消耗非常之大,看起來很嚇人。那麼這個GC到底是怎麼來的?又如何避免呢?

正文:

1、GetComponent 的GC來源

有一篇Unity的官方部落格:,其作者是 Lucas Meijer ,Unity的全球技術總監。其中提到了關於GetComponent 的GC產生來源:

We do this in the editor only. This is why when you call GetComponent() to query for a component that doesn’t exist, that you see a C# memory allocation happening, because we are generating this custom warning string inside the newly allocated fake null object. This memory allocation does not happen in built games. This is a very good example why if you are profiling your game, you should always profile the actual standalone player or mobile player, and not profile the editor, since we do a lot of extra security / safety / usage checks in the editor to make your life easier, at the expense of some performance. When profiling for performance and memory allocations, never profile the editor, always profile the built game.

大概意思是說,因為Unity重寫了Unity.Object的==方法,所以當使用GetComponent 獲取元件的時候,如果是個不存在的元件,就會產生警告字串。這就是GetComponent 的GC來源,但這個GC只會在編輯器下出現,而且只會在獲取到空元件的情況下發生。

2、測試

寫一個簡單的程式碼進行測試:


        private void Update()
        {
            GetImage();
            GetAnimation();
        }

        public void GetImage()
        {
            var img = GetComponent<Image>();
        }

        public void GetAnimation()
        {
            var ani = GetComponent<Animation>();
        }

這個掛載的物體掛有一個Image元件,而沒有Animation元件。然後執行起來,看Profile,效果如下:

雖然執行次數是同樣的,但是由於沒有Animation元件,所以產生了很多GC。而Image能獲取到,所以就沒有產生GC。至於是否是隻在編輯器下才會有,沒有測試過。這裡選擇相信一波Lucas Meijer吧。

後記:

雖然Profile是效能分析的利器,但是有的時候在編輯器的情況和真機情況下不一樣的。有時候在編輯器下看到的問題在真機上不會出現,這種時候就需要特別注意了。

就事論事的話,GetComponent 的GC是不用考慮對其進行優化的。不過個人還是希望Unity能讓他沒有GC算了,或者讓開發人員能選擇性地進行開關。