Unity5 Upgrade: One step forward, twenty steps back…
Back to Unity5!
Well, it’s been a few months since I did any development work. I had to get out there and earn some cash to fund my game development work. I was contracted to create the artwork for a match-3 video game (“Dr Popper”). I did some data management for a large corporation. And, as a bit of a change, did some commercial gardening! Which certainly beat sitting behind a desk for 8 hours.
Back when I made my last Unity related post, I had decided to migrate my Pool engine from Unity 4.6 to Unity 5. The new rendering engine looked amazing. The new physics system promised dramatic speed increases. And, you had access to the Performance Profiler. Who could turn that down? 🙂
Well, I can report that I’m very pleased with the performance profiler! But, I had problems with just about everything else Unity 5 had to offer. That’s not to say that I won’t be able to knock my project back into shape again, it’s just that my Pool engine has gone from being 80% complete to 30% complete. Not good when you need to get something on sale quickly.
The Old Physics Issue….
I already documented the problems that I had with the new physics engine here. The new system introduced some strange behavour to my game (what appeared to be Poltergeist activity). And it seems other developers had the same problem. I was contacted by a team last week who had developed a very popular Pool product with Unity 4.6. They had exactly the same issues as I had with the Unity 5 physics. But unlike me, they had an existing published product with thousands of existing players. For me, this is an inconvenience. For them, the update represents a major problem.
But that’s not all they’ll have to contend with. I’ve since discovered a couple more problems…
The New Baked Lighting Issue….
The rendering engine was one of the main reasons I wanted to update to Unity 5. I knew that the real-time Global Illumination was probably going to be beyond the mobile platforms that I had in mind – but the new Standard Shader looked pretty awesome. And it is. The materials editor in Unity 5 is now reminiscent of the Materials Editor in 3D Studio Max. Overall, it’s a lot nicer to use – and for PC games I think it will be fantastic.
However! There is one area in which the new Enlighten engine falls short. And that’s Ambient Occlusion shading. For anyone familiar with rendering techniques, Ambient Occlusion shading is a non-directional method of shading that can add heaps of definition to your scene. The shading is based on the structure of your geometry. It shades all the areas where you have recesses – such as the corners of a room, or where objects meet the floor. It is perfect for adding realism to your scenes and avoiding that ‘flat’ look.
Here’s an example of the my table with Ambient Occlusion shading only:
In Unity 4.6, I found it easy to bake Ambient Occlusion shading into my game environments. I had a nice looking Pool table in no time at all. But in Unity 5, it’s not so easy…
The reason is this: When setting up and baking your lighting, there are two types of light affecting your scene. Direct lighting, and Indirect lighting. Direct light is light that comes directly from a light source, be it a lamp or the sun. Indirect light is light that has already hit a surface and is being bounced between objects. For example, a red table top might receive white light directly from an open window, but bounce ‘indirect’ red coloured light elsewhere in the room.
When you set up Ambient Occlusion shading in Unity5, it will only affect the areas hit by indirect lighting or ambient light. If you have direct light casting onto the areas where you want your Ambient Occlusion shading, it will cancel it out. While this is technically correct, it makes it harder to get the nice AO shading into your game. I had to do a lot of additional work to get the shading effect onto my Pool table – and that was only possible by rendering an Ambient Occlusion map in an external program. There is a slot for an AO texture in the Unity Standard Shader – but that limits you to using the UV1 mapping coordinates, which was no good for me as my UV1s contained repetition. Unity developers – if you’re reading: Please give us the option to use the UV2 mapping coords for that Ambient Occlusion map! Or better still, give us the option to let the AO shading affect Direct Lighting. That would solve a lot of problems :).
While the new rendering engine is definitely impressive, I found it presented a lot more technical hurdles – so isn’t nearly as friendly to new developers. It also crashed, many many times…
The New Android Speed issue….
I’ve also stumbled across a third issue that is perhaps the most worrying. In Unity 4.6 my Pool engine prototype ran at a blisteringly fast speed – that was the one aspect of Unity 4.6 that truly blew me away. Well, that’s not the case with Unity 5. Once I’d fixed up the broken physics and got around to running the engine on my Android device, it was a sluggish mess. In fact, you couldn’t play it. In 4.6, you could swipe the screen to spin / aim the cue. Swiping now had barely any effect. I initially put this down to changes to the touch detection system (I had written all the touch controllers myself). But, then I figured it was probably just due to a drop in frame-rate.
So I wrote a small FPS monitor routine to check my frames per second. The game appeared to be running around 25-30fps. Which, I appreciate is good from the aspect of conserving the battery. But previously, I’m sure the build was pushing 60fps…
I initially blamed the new rendering engine and shaders. It was doing a lot more after all. So I fully optimized the artwork, reduced polys and combined textures onto single sheets. I removed the effects. However, these optimizations had no discernible effect. So I literally started turning off the Rendering Components – so the game would play, but the objects would not be rendered. This increased the game speed, but not by as much as it should have.
Comparing Unity 4.6 and Unity 5 Speeds
I decided to do a test, to see if Unity 4.6 really was a lot faster then Unity 5.0. Below are the results of the test. I initially set up two completely empty projects, one in Unity 4.6 and the other in Unity 5. The only elements in these projects are: the two text elements and the script that counts the frames and updates the UI. The only other difference, is the Unity 4.6 app is NOT using the Canvas for positioning the UI. It is using the old GUIText display method.
Same device, same code, very different result:
So even without any 3D rendering or major code overheads, there was a significant speed difference between Unity 4.6 and Unity 5 on an Android device.
I then noticed that a lot of people online were pointing at the UI Canvas as the source of the Android slow down. To test this theory, I loaded up the above 4.6 scene (without the Canvas) into Unity 5 and compiled it. This is the result running on the Android device:
(it was actually fluctuating around the 50 fps mark)
So in this test at least, the Canvas object wasn’t the cause of the slow-down. With identical code, and both without a UI Canvas, we had the same drop in performance between Unity 4.6 and Unity 5.
On my device (a Huawei Y300i) I dropped from an stable 62fps to a figure that fluctuated around 52fps. That’s an unavoidable 16% drop in performance over Unity 4.6. If we then factor in the new Unity 5 features, such as the rendering effects etc, then the slow-down has the potential to be considerably worse than 16%.
These are the main issues I’ve had in upgrading from Unity 4.6 to Unity 5. There have been additional problems in updating to Unity 5.1, with Mono Develop refusing to compile my existing code with the error “An item with the same key has already been added” shown. For a while I had apply a manual fix for this each time I loaded Unity (following the instructions here) – however the very latest patch fixes the problem.
Gripes aside, I still think Unity 5 is an incredible piece of software. Transitioning to a completely new rendering and physics engine was always going to be painful. Unity is a vast and complicated piece of software and there are bound to be problems along the way. These are fundamental changes and it would be naive to think that such an update could be seamless.
If I was starting a new project today, Unity5 would still be my platform of choice. I’m sure the Android performance situation will improve as the system is optimised. As for upgrading an existing 4.6 project, well – if it is highly dependent on the physics engine, then you may have to do a lot of work in order to get your product back up and running again. It does worry me that my prototype still has physics-related quirks, even though I’ve re-calibrated the physics settings a number of times now. And, the game will require a lot more effort before it looks as good as it did before. But, I can live with that for the raft of new features that Unity 5 brings to the table.