[Solved] Enabling/Disabling Canvas Creates GC Alloc

Hello all. I have come across a bit of a problem. I am trying to reduce GC Alloc in my game. I am using Unity 2020.3.3f1. So I have been deep profiling and fixing any GC Alloc produced. I have come across a problem where I am unable to reduce GC Alloc by enabling and disabling a canvas for hiding some images.

Everytime I enable or disable a canvas it creates a GC Alloc of 364B in editor and 256B in build. This isn’t created everyframe but is created everytime the player switches weapon because I have linked the weapon switch and crosshair together so that when the player switches a weapon a different crosshair canvas is enable or disabled.

So my questions are, is it possible to enable and disable a canvas without creating GC Alloc? If possible then how to do it?

Sharing my code, profiling pic and canvas hierarchy pic to give much clearer picture.

using GiantMech.Weapons;
using UnityEngine;

namespace GiantMech.UIs
{
    public class IconHelper : MonoBehaviour
    {
        [Header("IconHelper Local Properties")]
        [SerializeField] private Canvas _iconCanvas;

        private IWeapon _weapon;

        private void Awake()
        {
            TryGetComponent(out _weapon);
            _weapon.RegisterIcon(SetIcon);
        }

        /// <summary>
        /// This method hides/shows the icon.
        /// </summary>
        /// <param name="isShow">True means to show the icon, false otherwise,
        ///                      of type bool</param>
        public void SetIcon(bool isShow) => _iconCanvas.enabled = isShow;
    }
}

Line 16, weapon.RegisterIcon(SetIcon), stores the SetIcon(bool) method in a delegate for the _weapon to call whenever there is a weapon switch.

The above picture is of the deep profilling I did in the editor. I have highlighted the part where my code starts the GC Alloc and from there it is all Unity.

The above picture is the hierarchy where the canvas is located. I have highlighted the canvas and inside it are two images. G O means Game Object. This means that the weapon contains the canvas.

I have tried by removing the canvas from the weapon game object and placing it outside like a normal static canvas. I have also tried to enable/disable the image components only in the canvas but didn’t work. I have also tried to enable/disable the canvas gameobject to see what happens, which is a no no, and wasn’t surprised by the gc alloc byte in this approch.

When working with Unity’s UI I always follow Unite 2016 - Let’s Talk (Content) Optimization and Some of the best optimization tips for Unity UI. Those two links always had the answers that I am looking for but unfortunately in this case I can’t find any answer to fix this.

Any help/information will be much appreciated.

K Out!

1 Like

Alright guys I have solved the issue. Another idea came to me right after posting this thread. I am now getting 0B for enabling and disabling canvases in build. Let me share what I did.

I have one main canvas, which I have highlighted. This canvas contains two more canvases which contains one image each. The sub canvases are always enabled and are never disabled. Only the main canvas, IconCanvas, is enabled/disabled. This now does not generate any GC Alloc in build but in editor it shows 0.7KB is created, which are PreUpdate.IMGUISendQueuedEvents*(368B)* and GUI.Repaint*(368B)*, but that is not due to my code or enabling/disabling the canvases. This is probably some editor GC Alloc being created.

This was mentioned in the linked I provided but for some reason this just escaped my mind. I hope this helps anyone else who may come across this problem.

K Out!

5 Likes