I am constantly updating this answer, I will remove this message when I have stopped.
There is no magic bullet that will make it work right out of the box. It's a series of steps required to achieve good results.
Even though Unity is game engine, it can be used for many different purposes. It's very convenient to use Unity for mobile development or other PC applications.
Maxing out a device’s capabilities can quickly compromise your game’s performance by overtaxing the hardware, which leads to throttling, poor battery life, and inconsistent performance.
To decrease energy consumption of the application we need to make it do less, and that includes increasing it's performance as well, as we don't want to compute unnecessary things and make CPU, GPU, etc. to consume power.
There are lots of optimizations you could try to achieve a sufficient result.
If you need to get started on performance optimizations then this is a great place to start - Unite Europe 2017 - Performance optimization for beginners.
- First that comes to mind is on demand rendering. From provided stats I can see that 55.6% comes from GPU which is mostly responsible for drawing a frame. We want to reduce number of frames drawn per second to as low as possible. Usually good mobile frameworks work on events, they redraw and animate only things that are visible and only when something is happening on the screen, if a picture is static - there is no need to redraw it thus lowering energy consumption.
Rendering.OnDemandRendering - this feature appears to be available starting from
You can also control framerate using Application.targetFrameRate.
Additionally if the QualitySettings.vSyncCount property is set, the targetFrameRate will be ignored and instead the game will use the vSyncCount and the platform's default render rate to determine the target frame rate. For example, if the platform's default render rate is 60 frames per second and vSyncCount is set to 2, the game will target 30 frames per second.
To use it - you need to set
Don't Sync (?)[which I believe is an enum with a value of
0. That is why
QualitySettings.vSyncCount = 2 is mentioned in the documentation].
Note: changing target frame-rate affects input. To have frame-rate independent input - use New Input System that should be coming out of beta in
2020.1 [from experience, it's still in preview but is already pretty stable].
Limit processing on GPU to the minimum.
- Less heavy shaders.
- Faster renderers like Universal Render Pipeline, you can even write your own Render Pipeline to include only the things you need in rendering.
Limit processing on CPU to the minimum.
- Write optimized code.
- DOTS (?)[not sure about this one, but my intuition says it is faster == less processing == lower power consumption].
- Remove any packages you don't need (4) that use CPU.
Package Manager window you can remove lot's of packages that might be used by default. There you can select
Built-in packages and remove lots of things like
Physics for example, if you don't use any 3D physics in your application etc.
If you are using
UI in the canvas it tends to redraw often. When layout is changed it redraws a whole
Canvas. You can make use of shaders to manipulate some visuals to remove this dependency, or draw a
Canvas yourself. [I will elaborate on this later, it's a big topic and I am short on the time right now. I am not sure if this was fixed or not, so I will have to do more research and post some code examples maybe if they will be a fit.]
Overhead. The link has lots of useful information about overhead in Unity. Unity profiler in general does better job in giving information about processes that run in Unity. During comprehensive optimization I recommend using
Deep Profile in
Profiler window in Unity.
In the Profiler, the Overhead is the total frame time minus the duration of everything else that is actively measured. It is usually related to the internal processing of the scene. The more complex the scene, the more Overhead it will produce. It also accounts for the vertical synchronization that can be set to a fixed duration with Application.targetFrameRate.
The complexity of the scene does not refer directly to the amount of objects that compose it, but to the processing in general. If you have lots of objects, processing all of them will take more time than just a few. More importantly, the different engine sub-system tasks on those objects (in this case, tasks that are not being actively measured in the Profiler) will be added to this complexity, increasing the Overhead. Depending on the work performed, this increase could be significant or not. This means that it is not possible for us to provide statistics on the complexity of the scene since it depends on many factors.
The Profiler's hierarchy is populated with the processes that are most likely to consume important resources, but lots of hidden tasks will still remain. In order to find what is adding more complexity, or processing to the scene, you could remove or change "aspects" of the scene one by one, then profile and see how that affects the Overhead.
"Aspects" refers to the groups of objects that are processed by some sub-systems, that is 3D or 2D physics, navmesh, sprites, lighting, scripts and plugins, rendering, GUI, audio, video or particles, etc. The aspects could include settings used by the sub-systems. You might find one of these is considerably affecting the performance, and then you can optimize it.
There is a lot of information that I cannot fit in one post or even describe how it works in detail. So for further readings I have gathered some useful links: