- Home /
Optimized screens using new UI: SetActive() vs. nested Canvases vs. nested CanvasGroup
Hi,
Our game is 100% based on the new UI. I want to know your opinion about best performant optimized solution to make menus and screen transitions using the new UI.
Our original solution:
A root GameObject with a single Canvas + GraphicRaycaster. Child objects are game screens. Per game screen, I am using a root GameObject with a custom PanelScript and an animator for opening and closing animations. The animations are simple we just translate the screen panel in and out of the screen in one of the 4 directions using RectTransform's anchors.
After profiling, I realized that the animator is being (re)initialized every time I (re)activate the GameObject to which it is attached. The first time an animator instance is initialized takes longer than subsequent ones for same animator type as I guess there are some IO/serialization operations being done under the hood. So I was thinking I should have this executed during splash screen. Other than the animator's initialization, we decided to remove as many [H/V]Layout as possible and merge as many Text components as possible.
Now we came up with 3 different approaches to do more optimization and would like to know your opinion:
1. All screen GameObjects are active by default in the scene and will be deactivated once the first screen (splash) is opened. Toggle GameObject screens: SetActive(true) when a screen is about to be opened and SetActive(false) for the closed screen.
2. Keep all screen GameObjects active in the scene, have a disabled Canvas per screen (a GraphicRaycaster is required per Canvas, top one is removed though). Toggle Canvas: canvas.enabled=true when a screen is about to be opened and canvas.enabled=false for the closed screen.
3. Keep all screen GameObjects active in the scene, have a CanvasGroup with alpha=0f per screen. Toggle CanvasGroup: canvasGroup.alpha=1f when a screen is about to be opened and canvasGroup.alpha=0f for the closed screen.
Answer by RobAnthem · Dec 26, 2016 at 06:24 PM
From my having all your Canvases in one Scene is kind of nice and resorce-wise seems to have very little affect. Mainly because when you SetActive it disables the object and stops all code attached to it, making it SUPER convenient to hook into the OnEnable event. OnStart is great for initial stuff, but you'll get the OnEnable/Disable on every SetActive. The biggest issue I've seen is keeping it organized while you make new UI elements. For a while I was just making UI prefabs, but it became easier to ensure object positions with leaving it In-Scene and enabling/disabling. Of course you'll run into problems like your Animator, but even has you said, the additional loads reduce the time it takes. Perhaps you could keep the animator active elsewhere, and pass the reference to it as needed?
yes first approach has the big advantage of OnEnable/OnDisable! after reading your comment now I'm thinking if there is a way to have a single global animator that handles all transitions or even get rid of the animator and replace it with a custom script!
Answer by KnightRiderGuy · Dec 26, 2016 at 07:43 PM
I'm not sure if this helps or is even the proper way to doing it, I'm a novice at this stuff at best, but one method I'm using is that each canvas has panels, that can be set active by code. I have other canvases that have their own camera assigned to them and I have two game manager objects, one that tracks which canvases & panels are set active and another that tracks which cameras are set active.... we have a lot of tis going on something like 21 cameras and about as many canvases with sub panels, some of the panel's are animated so there is a game object that tracks and enables the animations too.... but it seems to work very well, but as I say i'm not sure if that is the recommended method, it's pretty much just what I've cobbled together ;).... but hey it works like a dream near as I can tell :)
your suggestion is good (having multiple cameras, one per canvas) but it requires a lot of refactoring from our side and we have all sub panels nested under one big GameObject/Canvas.
Thank, I can't see that being too big of an issue though, just use a panel manager game object to track which panels are active, say if one becomes active then it turns off the appropriate panels.... should work pretty nice even without having a camera for each canvas.
Your answer
Follow this Question
Related Questions
Just playing an animation in UGUI will cause GC allocation 0 Answers
Animator.Update has high CPU usage 2 Answers
[Optimization] - Is "Generate Physics shape", in Import settings, necessary for UI? 1 Answer
UI button pressed animation not playing directly after entering 2 Answers
Wierd flickering animation 1 Answer