I’m porting a game from Windows Phone 8 to Android, testing on a Nexus 7 tablet and a Nokia X - I’m noticing some strange behaviour with the font on the latter.
I use an oversized font (45 point) so that I can render titles, then scale down for smaller, “normal” text. On first run of an installation, this works fine on the Nokia X - but on the second run (ie: not re-installing), the font is replaced by black blocks. This happens in both debug and release configuration.
I tried different font files and sizes: the only change in this situation I saw was that using a 36 point font, on a third run the font reverted back to its correct state, but on the fourth it returned to black blocks again.
Any ideas as to what is going on? The font was compiled using Visual Studio 2010, using a PC project in debug build configuration.
I don’t develop for android, but read some threads here that said that using the backbutton would reset the graphics context, so you would lose all the loaded textures.
So in that situation one would have to reload all the textures.
check if it is that that it is happening with you.
I don’t think this is the case - this is the sequence that causes the problem:
Deploy to device and run: font is fine
Exit the game ie: game.exit is called
Restart the game: font is now replaced by black blocks
Interestingly enough, a second project with fewer assets that uses this same oversized font technique appears to work fine, so I’m wondering if the issue is down to how much memory the game uses…
This is true, some time ago all textures would be lost completely. There is now code in MonoGame.Android to detect the device reset (or context being recreated in GL speak) and reload your graphics assets. In particular it calls into SpriteFontReader passing your existing instance to do this, so it sounds like there is a bug somewhere there since it seems to be intermittent, or related to texture size.
Also, I believe a recent or upcoming version of Xamarin.Andriod has a fix in it which should remove this need to reload textures on most devices in the last few years (that is, it allows the GL context to be retained when the app is put into the background). Unfortunately I’m not sure when it will/did arrive in Xamarin.Android, but here is the issue link: http://forums.xamarin.com/discussion/621/androidgameview-pause-without-losing-gl-context.
When the game is cold-started and all the assets are first loaded, I store the filenames of all the spritefonts I use. When Activity.OnPause fires, I set all the spritefont variables to null and then fire the garbage collector.
When the game resumes, while the spritefont variables are null, the list of filenames remains - so then I can reload them in the Content.Load.
All Texture2Ds appear to be correct after the resume - it was just the font that was having trouble.
Moreover, I have another game on Android using the same underlying libraries that does not exhibit this problem.
I am using the NoHistory = true attribute on my Activity class, and I vaguely remember that this was following the advice I got from someone on the old boards following some kind of graphics issue.
Give me a shout if I can help with any further investigation.
I wonder if your SpriteFont is compiled from a texture or from a .spritefont file? Are you running MonoGame 3.2 or a recent version of develop from Github?
If you can reliable reproduce it by creating an empty project with just the problem font file, you could debug it by stepping through the Texture2DReader.ReadAsset() method, both on the first and second runs and see if the code paths are different. In the second run (game is resuming) you should see the Texture2D existingInstance parameter being non-null (it is passed in from the SpriteFontReader).
This is because I tend to have a horrible experience whenever I try to install or set up anything new that isn’t a one-click install - case in point, I bricked a macbook last night trying to install Xcode on it so I could port to and test on iOS! So once I’ve got something that works, I tend to stick with it.
I haven’t been able to reproduce the issue reliably outside this particular project - in fact another project using exactly the same libraries etc. prior to the fix works does not exhibit this behaviour! But I can always remove the fix code temporarily and step through as described, if this helps.