Unity - Heat - Optimize (Day 5)

Unity causes mobile heat...

Day 1 till 4, cried silently.
Day 5.

I've been testing with Unity optimization for mobile lately. My in-development game causes low-end Android devices heat ( I do not own a high-end one so I have no idea about the heat on that class ). Even though the FPS is steady above 60fps and game scripts are optimized to an acceptable level that never requires more than 5ms to finish, the phones heat up quite fast. More heat = more battery consumption = Your game is not optimized to be as good as that other game which is cool on hand. And that problem concerns me, days and nights.
My in-dev game is mainly in 2D, a lot of UI, much of 3D particles, and a dozen of sparkles.
In the past, I made this game on Cocos2D, and it was good, no heat, peak fps.
Then I decided to learn Unity as my new main tool. Unity came to me naturally, I love it and it loves me, maybe. My jump into Unity takes not so much effort. Easily, I beat the Animator, Data Handling, OOP, and Game Control in Unity. But now, I meet the boss - Device Heating.

I did search for similar problems and found out that I'm not the only victim, developers have a hard time coping with mobile heating. I tried their suggestion, some worked, some didn't. Below are what I've done and how they affect mobile heat problem. Hope those will help someone and someone will help me on his problem. I rate the results in 10-scale °C.

1. Optimize all scripts
The first time I noticed the heating was the time I did not group the PlayerPrefs.Save()
My Idle Clicking game requires Save() constantly. In order to reduce the number of Save() to call, firstly, I make sure that there is no constantly updated data need to save. The data will be saved only when level up, buy or unlock. Then I try to reduce the time of Save() being called. At the early stage, every time game saved anything, I called PlayerPrefs.Save(). That cost a lot as I checked on the Profiler. The game needs to save a DateTime variable, with which I have to cast it to binary then string to save. So I grouped all Save() into one call only in the LateUpdate() of my GameController, the LateUpdate will make sure that the Save() will be called after all other PlayerPrefs updates. If an object needs to save something, it will call PlayerPrefs.Set*() as normal then SendMessage to GameController to flag a Bool NeedToCallSave. And in the LateUpdate(), based on NeedToCallSave, call Save() and reset that flag.

Result: 2°C.

2. Kill the eye candy
Another problem, my game has too much eye candies. So I tried to remove as much as iI can in hope of reducing render workload. Some candies are added to the game when I hyped about the power of Unity. But that means a lot of overdrawn on the screen. Transparency is somehow - your enemy. So with a lot of pain in my heart, I remove most of my beloved Particles. Try to test every Particles System, reduce sub Particles as much as possible, combine with animation to achieve the same effect/feel, kill all transparency in color & Color over time. But I still managed to keep the feel of the game quite similar to the original so I can conclude that: My eye candies are unnecessary OR My skill in minimizing things is so good. I hope it will be more on the minimizing side.

Result: 1°C.
Surprisingly, after a lot of actions, not much heat reduced. But I think optimizing effect is crucial. Should do it and do it right when the project started.

3. Down the fps
Change Application.TargetFrame back and forth between 30 and 60 makes a significant change in heat. Halved the framerate reduce a lot of workload on rendering. But the animations look terrible.
So I decided not to.

Result: 2°C.

4. Turn off everything
Every Material is set to Mobile/VertexLit or Mobile/Particles. Lights are turned off one by one. Tried to dig into all light/reflect settings and turn them off. And set the Quality to low, no AA, no HDR, no shadow. Lighting is set to lowest possible. Luckily, the game keeps its level of quality. But the phone is still hot, not as I expected.

Result: 1°C

5. Down the resolution
Dig deeper, I found out that my game run on FullHD resolution even if it was designed for 640X1136. I think this is unnecessary, so I implemented a little check and change the resolution to at max 640px width. The result is so good. The phone is finally cool.

Result: 3°C

6. Batching
Unity can draw multiple sprites from a sheet in a single Draw call (as long as they do not much differ in Z, lights,...). Using Unity built-in Sprite Packer, the Draw Calls reduce from 4x down to 1x at max. But at this point, I can not say how much did this impact the heat of the phone, it is already cool. But checking the Profiler, I can see a lot of workloads has been released. The game now run at max 200fps.

Result: Maybe  2°C.

That's all Folks!

These above are my first attempts at optimizing Unity. Hope these can help someone facing the same problem.


Popular posts from this blog

Dota2 vs. LOL vs. Clash Royale vs. CATS