1. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  2. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  3. We’re giving 2017.1 beta testers a chance to win t-shirts and a Nintendo Switch. Read more on the blog.
    Dismiss Notice
  4. We want to know how you learned Unity! Help us by taking this quick survey and have a chance at a $25 gift card
    Dismiss Notice
  5. Are you an artist or level designer going to Unite Europe? Join our roundtables there to discuss artist features.
    Dismiss Notice
  6. Unity 5.6 is now released.
    Dismiss Notice
  7. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice

Massive Font.CacheFontForText CPU spike using default GUI

Discussion in 'Extensions & OnGUI' started by invicticide, Feb 7, 2014.

  1. invicticide

    invicticide

    Joined:
    Nov 15, 2009
    Posts:
    98
    The first time I draw anything using the default GUI (no custom fonts, skins, or styles) I get a *huge* CPU spike in Font.CacheFontForText:

    $profiler-wat.png

    I found a UnityAnswers thread that suggests that this can happen with dynamic fonts when attempting to render glyphs that aren't currently in the font map, and that using a static font is one way to resolve the issue.

    However, since I'm using the default GUI font, I don't have access to any import properties, because it's not an asset in my project.

    Is there anything I can do about this?
     
  2. hellaFont

    hellaFont

    Joined:
    Jun 6, 2013
    Posts:
    4
    I believe the default font is arial, you could just import an arial font into your project and use that.
     
  3. Trof_Sivart

    Trof_Sivart

    Joined:
    Dec 15, 2013
    Posts:
    8
    Just solved a similar issue to what you're having. In my game, I was using multiple GUIstyles to display powerup icons. When there was no font attached to them (default was none), whenever I got my first powerup I would get about 800ms lag, then it would be fine for the rest of the playthrough. My solution was to assign a font to each of the GUIstyles, and it got rid of the lag. Hopefully this information is helpful to you :)
     
  4. droido

    droido

    Joined:
    Jan 27, 2014
    Posts:
    9
    got mine fixed with Rendering Type - OS Default
    previously it was Smooth.
     
  5. MrEsquire

    MrEsquire

    Joined:
    Nov 5, 2013
    Posts:
    2,595
    I seem to be having this issue with Unity 4.6 Beta 20, not sure whats causing it..

    On iOS Mobile 50percent CPU spike;
    Canvas.SendWillRenderCanvases()
     
  6. Andy-Block

    Andy-Block

    Joined:
    Aug 10, 2012
    Posts:
    10
    I'm also seeing this on b20 on Android. 150ms spike on a Galaxy SII
     
  7. DennG

    DennG

    Joined:
    Dec 5, 2013
    Posts:
    158
    I'm also facing the same problem. I'm downloading 4.6 RC1 right now to check if the problem has been solved.

    Edit:
    Working fine with RC1. Good job unity team.
     
    Last edited: Nov 8, 2014
    MrEsquire likes this.
  8. TheWulo

    TheWulo

    Joined:
    Nov 16, 2014
    Posts:
    4
    I have the same problem.

    Even after setting the .tff font rendering mode into OS Default it still gives me spikes.

    I'm using 5.0.0b13, so probably I will need to wait for the same patch that solved the case for DennG.
     
  9. DennG

    DennG

    Joined:
    Dec 5, 2013
    Posts:
    158
    The problem is still there. But it's much better than before.
    I hope that the UI team is working on this performance issue...
     
  10. jay-jang-archiact

    jay-jang-archiact

    Joined:
    Jul 21, 2014
    Posts:
    1
    When will this get fix!

    I made a static font instead of dynamic one, and bug is fixed, but I can't have it bold.
     
  11. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    184
    Hey there,

    Try changing your text to not using Best Fit and go to your font file and don't make it dynamic. Unity is trying to rebuild your font into a texture every time a letter is added or removed. This has a huge overhead as it's baking a texture behind the scenes.

    Regards,
     
  12. IVxIV

    IVxIV

    Joined:
    Nov 13, 2013
    Posts:
    12
    For anyone else who encounters this same issue, here is another solution you could consider. I ran into the same problem as a result of using custom GUIStyle objects for rendering in my OnGUI calls, some of which referenced custom dynamic fonts (this is the source of the problem - dynamic font glyphs get cached to an internal font cache texture in Unity).

    To avoid taking the big hit all at once when Font.CacheFontForText() is first called by means of an OnGUI call, inside an Awake() call for my UI code I spin up a coroutine to asynchronously precache each of my dynamic fonts' glyph data, making repeated calls to Font.RequestCharactersInTexture(). This has worked nicely so far for my relatively simple UI needs, and avoids having one giant blocking stall where the GUI font cache is populated all at once.

    Here is some sample code to illustrate the basic approach I used:

    Code (CSharp):
    1.  
    2. public class MyGUIClass : MonoBehaviour
    3. {
    4.     private static readonly string kPrecacheFontGlyphsString= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\\:;\"'<>,.?/ ";
    5.  
    6.     // utility struct used in font caching
    7.     struct CacheFont
    8.     {
    9.         public Font theFont;
    10.         public int size;
    11.         public FontStyle style;
    12.     };
    13.  
    14.     void Awake()
    15.     {
    16.         // gather custom fonts that we will be using
    17.         CacheFont[] myCustomFonts= RetrieveMyCustomFonts();
    18.  
    19.         if (null != myCustomFonts)
    20.         {
    21.             for (int fontIndex= 0; fontIndex < myCustomFonts.Length; ++fontIndex)
    22.             {
    23.                 StartCoroutine(PrecacheFontGlyphs(
    24.                     myCustomFonts[fontIndex].theFont,
    25.                     myCustomFonts[fontIndex].fontSize,
    26.                     myCustomFonts[fontIndex].fontStyle,
    27.                     kPrecacheFontGlyphsString));
    28.             }
    29.         }
    30.      
    31.         return;
    32.     }
    33.  
    34.     // Precache the font glyphs for the given font data.
    35.     // Intended to run asynchronously inside of a coroutine.
    36.     IEnumerator PrecacheFontGlyphs(Font theFont, int fontSize, FontStyle style, string glyphs)
    37.     {
    38.         for (int index= 0; (index < glyphs.Length); ++index)
    39.         {
    40.             theFont.RequestCharactersInTexture(
    41.                glyphs[index].ToString(),
    42.                fontSize,
    43.                style);
    44.             yield return null;
    45.         }
    46.      
    47.         yield break;
    48.     }
    49.  
    50.  
    51.     void OnGUI()
    52.     {
    53.         // now that dynamic font glyphs have been precached,
    54.         // there won’t be a terrible hitch the first time this is called
    55.     }
    56. };
    57.  
     
    Last edited: Dec 24, 2014
  13. wangunity

    wangunity

    Joined:
    Sep 25, 2013
    Posts:
    3
    do you have any idea when come to NGUI project ?
     
  14. IVxIV

    IVxIV

    Joined:
    Nov 13, 2013
    Posts:
    12
    No, but if you needed something like this for NGUI (assuming it doesn't already have it built-in), then it should be straightforward to add.
     
  15. MrEsquire

    MrEsquire

    Joined:
    Nov 5, 2013
    Posts:
    2,595
    I think this issue still exists with the new GUI and Unity 4.6.2p1
     
  16. Icaro Malta

    Icaro Malta

    Joined:
    Jan 21, 2013
    Posts:
    5
  17. MrEsquire

    MrEsquire

    Joined:
    Nov 5, 2013
    Posts:
    2,595
  18. nevilleshane

    nevilleshane

    Joined:
    Aug 19, 2013
    Posts:
    3
    I fixed this by unchecking 'Incl. Font Data' on the font file.

    Switching the actual font from Dynamic also worked, but it caused some additional logistics headaches.
     
  19. Chintao

    Chintao

    Joined:
    Jun 26, 2014
    Posts:
    54
    Thank you! I had the same problem with my game and i just disabled Best Fit for all of my text elements and it's working ALOT better now! I still have the font dynamic cause without it looked washed out.

    again thank you!
     
  20. Tomer-Barkan

    Tomer-Barkan

    Joined:
    Jul 31, 2012
    Posts:
    92
    I'm now getting this spike every minute or so, and the spike is 1500 miliseconds... :(
    This started when upgrading to 5.2.1. When I build with my other PC that still has 5.1.1 this issues do not occur, and a bunch of other errors and warnings as well.

    upload_2015-10-5_21-12-35.png
     
    BernieZQ likes this.
  21. TriBolt72

    TriBolt72

    Joined:
    Jan 27, 2015
    Posts:
    7
    I'm having issues with this as well...
     
  22. rcabot

    rcabot

    Joined:
    Oct 24, 2014
    Posts:
    1
    Just a heads up, I solved this with a really silly workaround.
    If you don't disable and reenable your UI components, and instead move them off the screen so they're not seen, unity won't recache your font textures:
    Code (CSharp):
    1. private void ShowRightPane(bool shown)
    2.     {
    3.         RightPane.GetComponent<RectTransform>()
    4.             .transform.localScale = shown ? new Vector3(1f,1f,1f) : new Vector3(1f, -1f, 1f);
    5.     }
    Not particularly scalable, but good enough for a small project, and it completely removed the horrible spike I was having.
    So if you don't absolutely need to, try just not disabling the game objects your UI Text sits on!