You spend an infinite amount of time optimizing your Unity UI. But, all it takes to really screw up performance is a sneaky modification on a tiny attribute of an almost invisible Canvas UI element. And when that happens, not even Unity UI Profiling will save you from dropping frames. Are you ready for the road ahead?

This is what happened in my last project... I worked hard to optimize the several UI panels of our port to Oculus Quest. This was mostly about reducing the overdraw level to an acceptable amount to make sure the GPU would be all comfy with the real 3D rendering. So I worked on Unity UI Optimization for at least a month and made pretty damn good progress. At some point, it was so well optimized that the GPU timings were barely moved by the UI. The opaque UI shading techniques I applied compensated most of the overdraw caused by UI Layering (elements drawn on top of other elements).

There I was, with a super optimized hybrid UI system that effectively occluded the 3D elements drawn behind it. It became very easy to discard the rendering of these occluded fragments. However, I was far away from being done...

When I hooked the Unity UI Profiler, one thing caught my attention.

I saw an overwhelmed CPU taking over 1 ms per frame on UI rendering. That's a hell lot of time for a platform that gives you a budget of 13 ms for the whole game execution: physics, logic, 3D rendering, input, VR, networking are all in the same bucket. And I've seen cases where UI kills CPU performance even more.

And that is the thing: UI can be optimized to be GPU-friendly, but that doesn't directly translate into being CPU-performing. In fact, CPU and GPU have very different tasks to accomplish in Unity UI Rendering. No wonder, I suggest you approach CPU and GPU optimization very differently, as seen in my previous blog post about Unity UI Optimization. Doing more of Unity UI Profiling showed me the obvious problem: the UI was constantly being re-created every single frame, i.e. there was a Canvas Rebuild happening every frame. A constant hit of 1 ms on the CPU... ouch.

But why would Unity do this to me?

I thought Unity cached the UI Canvases...