关于 Unity 的 GetComponent 函数所产生的GC问题

前言:

最近的项目优化GC,其中看到关于GetComponent的GC消耗非常之大,看起来很吓人。那么这个GC到底是怎么来的?又如何避免呢?

 

正文:

1、GetComponent 的GC来源

有一篇Unity的官方博客:《Custom == operator, should we keep it?》,其作者是 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();
        }

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

这个挂载的物体挂有一个Image组件,而没有Animation组件。然后运行起来,看Profile,效果如下:

虽然执行次数是同样的,但是由于没有Animation组件,所以产生了很多GC。而Image能获取到,所以就没有产生GC。至于是否是只在编辑器下才会有,没有测试过。这里选择相信一波Lucas Meijer吧。

 

后记:

虽然Profile是性能分析的利器,但是有的时候在编辑器的情况和真机情况下不一样的。有时候在编辑器下看到的问题在真机上不会出现,这种时候就需要特别注意了。

就事论事的话,GetComponent 的GC是不用考虑对其进行优化的。不过个人还是希望Unity能让他没有GC算了,或者让开发人员能选择性地进行开关。

 

 

 

 

 

你可能感兴趣的:(Unity)