Tavados
Tavados

Reputation: 2308

Unity3D invisible Canvas performance

I'm developing a 2d menu heavy mobile game, which uses a lot of canvases, panels, popups etc. In the beginning I had all menus active at all times, but only the ones that the user can use lie within the frustum (i.e. the others are just translated out of sight). Then I switched to deactivating the menus that the user can't see, just to increase the game performance. This however causes many inconveniences for me, like e.g. state variables in the Animator component resetting when de- and reactivating a GameObject.

So what is the best way to do this? Is the deactivation of temporarily unused canvases even worth it, or is Unity automatically clipping away the UI that lies out of the frustum, so there's basically no performance cost?

Upvotes: 0

Views: 3599

Answers (3)

Roberto
Roberto

Reputation: 11953

According to this Unity optimization document, disabling the Canvas (not deactivating its Game Object!) is the best way to hide it.

It's cheap to disable and re-enable the Canvas.

Upvotes: 1

Umair M
Umair M

Reputation: 10750

As you said your game is menu heavy, even disabling/enabling can cause overhead. This is something I have faced this in one of my projects in past.

A word of advice is to use Canvas Group on your menu objects and change their alpha (0 = closed, 1 = opened), Interactable and BlockRaycasts parameters.

If you have menu script on every menu/panel just disable/enable that on open/close.

enter image description here

Update:

Typical uses of Canvas Group are:

  • Fading in or out a whole window by adding a Canvas Group on the GameObject of the Window and control its Alpha property.
  • Making a whole set of controls non-interactable (“grayed out”) by adding a Canvas Group to a parent GameObject and setting its Interactable property to false.
  • Making one or more UI elements not block mouse events by placing a Canvas Group component on the element or one of its parents and setting its Block Raycasts property to false.

Other references:

https://www.youtube.com/watch?v=wbmjturGbAQ

https://github.com/Unitarian/Unity-Extensions/tree/master/Menus

Hope this helps

Upvotes: 3

Dreik
Dreik

Reputation: 140

How about creating interface like

public interface IOpenable
    {

        bool IsClosed { get; set; }

        void OpenWindow();
    }
}

then make every element subscribe to some controller and that controller can handle everything like so

public class MenuController: MonoBehaviour
{
    public List<IOpenable> MenuList;

    void Awake()
    {
        MenuList = new List<IOpenable>();
    }
    public void TryClose(IOpenable sender)
    {
        foreach (var i in MenuList)
        {
            if (!i.IsClosed && !sender.Equals(i))
                        i.OpenWindow();         
        }
    }
}

This way you can try to close all other windows you don't need while opening a new one. This is just a rough idea but it seems clean and fast for me.

Upvotes: 1

Related Questions