Hi !
It has been a very long time since I needed to use dynamic fonts but here it is again.
Doing so, I see there is still an issue in current NGUI's version when new characters are added that overflow current font’s texture size : during one frame, garbage can be seen.
I already proposed a patch some years ago that tried to fix that issue, and here I am with a new version based on latest NGUI, which seems to work well, at least in my case :p.
This time, I'll explain all the changes :
- Label that were marked dirty with MarkAsChanged where not actually updated geometry wise. that's why the issue is still visible in current NGUI -> I added a call to label.UpdateGeometry.
- Updating labels can lead to new OnFontChanged calls to be done recursively, which would invalidate previous geometry updates, so instead of updating geometry immediately I keep all labels that needs to be updated and only do it once, when we actually exit recursion.
- For the same reason a label may be updated several times, which is useless. So instead of storing draw calls to be updated, I store labels to be updated, and only do so once for each when exiting recursion.
- Updating a label’s geometry can cause a OnFontChanged to be triggered because of the UpdateNGUIText call it mades which tries to get font metrics. To prevent that to append when exiting recursion I manually call UpdateNGUIText of labels when I store them for future update.
- I use HashSets instead of Lists : iterating over them is slower than with Lists but lookups are faster. Since we iterate over them once per recursion exit, and we do lookups once for each label of updated font, it should be better.
- I pre-initialized them to avoid runtime null check. In the case where we uselessly created them, memory impact is really negligible.
You can try this with the project I attached to this message by following this protocol :
- before each test, reimport "res/eurofighter/Font Texture" asset, so that all cached data is cleared (sometimes need to do it twice, just check the texture is empty once done)
- start the application
- click somewhere in the screen
- with current NGUI, see there is a glitchy frame (the project sets frame rate to 2FPS when it starts so that you have a chance to see it)
- with patched NGUI, see there is no more glitchy frame