[Optimization] What's better between big hierarchy and instantiating a prefab ?

Hello everyone,

I have in my game a menu with a scrollable list of 42 buttons (here called ShapeButton), and each of them has an animator and a subhierarchy of images + texts.
This is a menu that is outside of my core loop, meaning it is only active when the player opens this page. When player closes the page, I deactivate the Canvas GameObject (which is the root of this whole hierarchy, highlighted in the screenshot).

What’s best in terms of pure optimization ?
Because this canvas lives on its own, does it “eat” any kind of performance while its deactivated ?
If so, should I make this whole page a prefab, and instantiate it only when needed ?

Thanks for your support !
Pierre

The answer to “which is faster” will always be “the one that the profiling analysis data says is faster.” Use the profiler.

In general, as a guess toward answering the question, there is a performance hit to certain functions like FindObjectsByTag when there are a lot of objects in the scene, active or not. It takes actual time to ignore things that are there but inactive. But your situation may not be hitting those functions that much.

Start with the simplest design that achieves your goal, and measure the performance to see if it is the worst thing in the whole game. If you are optimizing anything that is not the WORST THING IN THE WHOLE GAME, you are actively wasting your own time even thinking about it. Always work on the worst bottleneck first, and then the next worst bottleneck which is now the worst, and so on, in that order.

1 Like

Hi Halley!

Thanks for your quick reply! That’s an interesting and wise perspective :slight_smile:

I’ve actually done a good number optimization passes already, so now I’m trying to go a bit deeper.
Indeed I don’t really use methods which involve “find”, besides at very specific moments like game startup.

The thing however with looking at the profiler is that I have no clue on what such a big hierarchy could affect. Should I look at the CPU ? Memory ? Rendering ?

First, 42 buttons is not a big hierarchy at all. Think of games with thousands of trees and hundreds of little prop items in every room. You’re likely in the weeds here.

If you don’t see a spike in the profiler data when using various features of your game, then you don’t have a bottleneck that is worth your time.

Alright, makes sense, thanks a lot Halley !

There is no “pure optimization.” That’s not a thing.

Are you optimizing for correct code?

Are you optimizing for simplest code?

Are you optimizing for least memory use?

Are you optimizing for fastest CPU execution?

Are you optimizing for fastest GPU execution?

Are you optimizing for sharing your code with a large team of people?

Every single one of these things runs counter to the other in some axis.

In summary:

For all performance and optimization issues, ALWAYS start by using the profiler:

Window → Analysis → Profiler

DO NOT OPTIMIZE “JUST BECAUSE…” If you don’t have a problem, DO NOT OPTIMIZE!

If you DO have a problem, there is only ONE way to find out: measuring with the profiler.

Failure to use the profiler first means you’re just guessing, making a mess of your code for no good reason.

Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

https://discussions.unity.com/t/841163/2

Remember that you are gathering information at this stage. You cannot FIX until you FIND.

Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

Don’t forget about the Frame Debugger either, available right near the Profiler in the menu system.

Notes on optimizing UnityEngine.UI setups:

https://discussions.unity.com/t/846847/2

At a minimum you want to clearly understand what performance issues you are having:

  • running too slowly?
  • loading too slowly?
  • using too much runtime memory?
  • final bundle too large?
  • too much network traffic?
  • something else?

If you are unable to engage the profiler, then your next solution is gross guessing changes, such as “reimport all textures as 32x32 tiny textures” or “replace some complex 3D objects with cubes/capsules” to try and figure out what is bogging you down.

Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

This sort of speculative optimization assumes you’re properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.

“Software does not run in a magic fairy aether powered by the fevered dreams of CS PhDs.” - Mike Acton

Thanks for the comprehensive answer Kurt !

To your first question, my game will be releasing on mobile worldwide where some low end devices might run it.
But yes, maintenance is indeed a very valid point.

I actually just wanted to know if there was a simple rule of thumb regarding my very first question but looking at both of your answers I understand there might not be! I haven’t observed any specific issues yet (at least with the devices I’ve tested on ; I have a couple but it’s quite hard to anticipate all hardware behaviors).

There is!!

“Do less stuff and do that stuff less often.”

Mobile targets have an incredibly wide range of performance specifications. Fortunately this is mitigated somewhat by targeting a recent OS, but even then, the min-to-max difference can approach two orders of magnitude easily.

Not only that but mobile targets are all over the place between CPU, GPU, memory, flash ram access, etc.

What is constant is that we humans make our games, and we humans (at least me humans) are performance limited in terms of complexity and comprehension.

I optimize my code to do as little as possible as simply as possible. Complexity will happen anyway, so why encourage it early on?

ALSO, this may be relevant:

The costs and issues associated with object pooling / pools:

https://discussions.unity.com/t/892797/10

https://discussions.unity.com/t/833104/2

In very rare extremely-high-count object circumstances I have seen small benefits from pooling.

In 100% of ALL circumstances, object pooling is a source of constant bugs and edge case disasters.