I’m making a game for Android using Unity.
When I test my game on my Nexus 4, the GUI sometimes refuses to render parts of the text I give it. This problem doesn’t occur when I test on my brother’s Galaxy S3.
I took the first screenshot below by opening the game and going to the options screen. Then I went back to the main menu and opened the options screen again to take the second screenshot. Notice in the 2nd screenshot how the “fill” of most the text is missing.
I have two versions of my font, the normal one and an outline version. To render the text, I just use GUI.Label twice, once with the a GUIStyle using the normal font and a light blue colour then again using a different style that uses the outline font and a very light grey colour. I use the exact same Rect and GUIContent both times, so the only way for it to look like the second screenshot is if it simply isn’t rendering some of the characters with the background style, but is with the outline style.
Also note that the letters not rendered can sometimes change when I go to a different menu screen or run a level again and go back.
[13143-my+font+normal.jpg|13143]
[13144-my+font+broken.jpg|13144]
Code Structure:
-
The fonts are loaded from my Resources folder and the GUIStyles are created in code (C#) as static variables in a GuiUtils class.
-
The menu scene contains the background and a camera with my LevelSelect script on it.
-
In LevelSelect.Awake(), I create a DualLayerGuiText for the title and for each level button. Options.Awake() basically does the same thing for its stuff.
-
DualLayerGuiText takes a string, a Rect and two GUIStyles in its constructor. When I tell it to draw, it calls GUI.Label(Rect, string, GUIStyle) with the background style I gave it then again with the outline style (both of which are references to the static GUIStyles created in GuiUtils.
-
To change between the LevelSelect and Options screens, I disable the current script then enable the other one (if the other script doesn’t exist yet, I add it). So when the LevelSelect screen wants to load the options screen:
this.enabled = false;
Options options = GetComponent();
if(options == null) gameObject.AddComponent();
else options.enabled = true;
Notes on the Bug:
-
It never occurs when the menu scene first loads, only after you go to the options screen at least once.
-
It doesn’t occur on my brother’s S3 or in a PC build (or in the editor), only on my Nexus 4.
-
It doesn’t log anything to the android catlog.
-
It still occurs if I remove the outlines and make DualLayerGuiText only render the base text. The same applies if I remove the base and keep the outlines.
-
It still occurs if I use the default Unity font (by passing my stuff null instead of loading my Font from Resources), although it is slightly different. Since it isn’t using an outlined version of Arial, you can only see the front layer of text (using the outline colour) but not the back layer (using the fill colour). So wherever I can’t see a character that should have been drawn, in this case it means that neither layer has drawn that character.
-
It still occurs if I change the enabling and disabling to always use GameObject.Destroy() and gameObject.AddComponent<>().
-
It still occurs if I put both screens in the same MonoBehaviour and give it a bool telling it which screen to show. I thought the bug might have something to do with deactivating the MonoBehaviour in the middle of the OnGUI() function when the button is clicked. But having it as a bool means that when the button is clicked and the bool changes, the current screen finishes drawing and the bool is only checked again at the start of the next OnGUI() call.
-
It doesn’t occur if I replace the screen changing code with normal scene loading (having each screen as a single script on the main camera in its own scene). Unfortunately, this method has a noticeable moment of lag as the scene loads where my above method is instant. I’m also not sure if this even fixes the problem or just covers it up. The same problem could (should) theoretically occur in the game once you finish a level and it stops drawing the game’s HUD and shows your results (time to complete etc) over the top of the game (without changing scene).
Obviously for now I’ve changed my code to use normal scene loading (as per the last point above), but I’d really like to find out what this bug actually is.