Unity 4.2.2 to Unity 4.3 Experience Report

I recently ported a large and very well-tested game from Unity 4.2.2 to Unity 4.3. Although 4.3 is very new, the rendering engine in 4.2.2 contains a number of serious bugs for mobiles and the fixes to those rendering issues are only available in 4.3, so my options are limited. Since I know other Unity developers are considering upgrading to 4.3, I wanted to document my experiences bringing a complex 3D Action RPG called The Shadow Sun into Unity 4.3.

1403319--72933--$tss1s.jpg

Mouse Scroll Wheel
After upgrading from Unity 4.2.2 to Unity 4.3, one of the first problems that I encountered was that my trusty Apple Mighty Mouse no longer worked correctly in MonoDevelop. In particular, the mouse scroll wheel did not work in the code editor. This seems to be a defect in the version of MonoDevelop (4.0.1) that ships with Unity 4.3. The problem only affects certain types of mice and is perhaps fixed in MonoDevelop version 4.0.3 which doesn’t help me very much. I suppose simplest workaround is to purchase a new mouse?

FPS Reduction
In a small number of the scenes in my game, Unity 4.3 reduced the rendering speed from around 60 FPS to around 30 FPS. In most scenes, the frame rate is unchanged from Unity 4.2.2. I have not located the root cause other than that CreateVBO is slower in 4.3 but only along certain sight lines in certain scenes.

Meta Files
With 4.3, Unity now requires that all projects use meta files. So if you haven’t been using Unity’s built-in version control, you might be surprised to see your source directories littered with hundreds of mysterious meta files.

Invisible Player Character
After upgrading to Unity 4.3, sometimes my player character would disappear temporarily when walking around in certain levels containing fog. Although I think this problem has been around for years, the behaviour is certainly different between Unity 4.2.2 and Unity 4.3. I would have noticed my player character vanishing in 4.2.2! After many hours of debugging, I traced the problem to the way that Unity compiles GLSL shaders at run-time. While running your game, look in the Xcode console for a strange error:

-------- GLSL error: ERROR: 0:81: Use of undeclared identifier '_patchFragColor'

The error is strange because none of my shaders use anything called _patchFragColor! My best guess is that Unity secretly modifies our GLSL shaders to handle fog automatically. However, if your GLSL shader includes a conditional structure which references gl_FragColor in multiple branches, Unity breaks the shader by inserting a _patchFragColor variable definition in the wrong spot. Take a look where Unity placed the definition of _patchFragColor:

*
#ifdef VERTEXLIGHT_ON
* * *#ifdef PIXEL_POINT_LIGHTING
* * * lowp vec4 nonRampLighting = NonRampLighting(vectorsTo4Lights_tangent, normal, intensitiesFor4Lights);
* * *lowp vec4 _patchFragColor;
#endif
* * *_patchFragColor = mainTex * nonRampLighting + rimAndSpecular;
* _patchFragColor = _patchFragColor * _unity_FogVar +_unity_FogColorPreMul; gl_FragColor = _patchFragColor;
* * #else
* * *_patchFragColor = mainTex * _Color + rimAndSpecular;
* * #endif

The simplest work-around is to only reference gl_FragColor outside of a conditional. I think Unity’s parser is blindly scanning for the first mention of gl_FragColor and simply inserting the _patchFragColor variable definition immediately above that line. It’s a little spooky.

Vanishing Tiles While Moving
After upgrading to Unity 4.3, tiles directly in front of the camera randomly vanished while walking around. I solved this occlusion problem by decreasing Unity’s “smallest occluder size” from the default 5 to 1. In one particularly troublesome scene, I had to use 0.75. The disadvantage of this solution is that the size of the occlusion data stored in memory increases. Because of this, the occlusion data in my game now consumes more memory than earlier versions of Unity. For example, one of my scenes now requires 1.5M of occlusion data in 4.3 when it used less than 500K of occlusion data in Unity 4.2.2.

Vanishing Tiles During Camera Pan
When compared to previous Unity releases, the 4.3 occlusion culler is more sensitive to the camera sliding into walls. In our game, if the player is facing a wall and spins the camera around in a complete circle, the camera must pass between the player’s body and the wall. Sometimes the camera moved through the wall a tiny bit. At this point, Unity’s new culler blanks everything out. The fix was to adjust the minimum camera distance by a small amount so that the camera does not slide too far into the walls.

Vanishing Tiles In Hidden Rooms
In my game, clever players can spot several secret rooms hidden behind the crumbling sewer walls. In Unity 4.3, most of the geometry within these secret rooms is culled even when the camera is inside the secret room. No amount of fiddling with the occlusion settings helped. There are no non-static doors leading into these rooms so my assumption is that Unity’s new culler doesn’t expect the player to ever get inside these areas since there is no walkable path. I also saw the same problem in scenes which had several different “sections” which were not physically connected. The best work-around was to carve artificial non-static “doors” leading into the secret areas. This reduces the effectiveness of the culler, but at least it works. Note that this was not an issue with Unity 4.2.2’s culler.

Incorrect Occlusion Data
According to the documentation, the StaticOcclusionCulling.umbraSize property is supposed to return the size of the baked occlusion data. This property always returns zero even after a scene is baked. I don’t know of a workaround, other than to not use this property.

Stale Occlusion Grids
If you bake a scene in the editor and then open another scene, you’ll still see the previous scene’s occlusion data super-imposed in blue over top of the new scene. Fortunately, this seems to be only a visual glitch.

your analysis is quite right about fog patching and stuff. Please, totally bug report it with shader in question - it should be pretty doable to have it fixed in 4.3.1 or smth

Alexey, I suggest you let Kevin into Unity’s Beta (Even closed-Alpha) Usergroup. His posts are golden.

Thank you Kevin for taking the time to do this. It’s appreciated. Although bug-reports allows Unity to fix those issues, ultimately it’s the community support that motivates developers to grind through those bugs and report them.

Also noticed (and reported) the Stale Occlusion Grids.
On top of that I am having an issue with occulsion baking sometimes not finnishing and sitting here for ages with a full progress bar.
Kinda seems a bit random but this started with 4.3.

After spending some more time working on The Shadow Sun game, here are some updates to my earlier comments regarding porting a game from Unity 4.2.2 to Unity 4.3. Good luck with your Unity 4.3 projects!

Occlusion Culling
Getting 100% accurate results from the new culler is very difficult. Eventually we resorted to hand-managing the bake parameters on each of the 70+ scenes in the game. For example, in one scene using a “Smallest Occluder” size of 1.0 resulted in props vanishing when directly in front of the main camera. Changing that same parameter to 1.05 solved the issue. Changing that same parameter to 1.10 resulted in props vanishing again. We could not identify any discernible pattern so we proceeded through a long process of trial-and-error. The only good news is that if you spend enough time, it’s possible to solve every occlusion issue. For more information, please read this post in the iOS forum.

Incorrect Occlusion Data
Unity has changed the StaticOcclusionCulling.Compute method from a synchronous invocation to an asynchronous invocation. The StaticOcclusionCulling documentation was updated to show the new syntax but says that the Compute method is synchronous. The documentation is incorrect; before reading StaticOcclusionCulling.umbraSize, you must wait until the bake finishes. The only way to do this is to busy-loop on StaticOcclusionCulling.isRunning.

Hello Kevin,

Thank you for sharing this.

Follow up question; have you tried to benchmark Unity’s occl. culling solution with zone culling solutions like M2H Culling (http://forum.unity3d.com/threads/52130-M2HCulling-Optimize-your-game-culling-system-for-Unity) ?

Reading through the forums, the CPU overhead of Umbra appears to not be worth it as Unity is already quite CPU intensive ending costing more than the draw calls saved. What’s your take on this?