Search Unity

What should I optimize first in this section of code?

Discussion in 'Scripting' started by WarpZone, May 7, 2018.

  1. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Rolled my own solution for putting text on the screen during Update. Didn't use coroutines because I need precise timing relative to a sound effect's length and I seem to recall coroutines always dropped the ball with that kind of thing.

    Anyway, this works perfectly, but it halves my frame rate. What can I do about it?

    Code (CSharp):
    1.  
    2. if(timeSinceBossSpawn <=  (timeBetweenCharacters * numberOfCharacters)) {
    3.     bossDescriptionText.enabled = true;
    4.     int currentCharacter = Mathf.FloorToInt( timeSinceBossSpawn / timeBetweenCharacters );
    5.     if(currentCharacter < bossDescriptionString.Length){
    6.         bossDescriptionText.text="";
    7.         for(int i = 0; i < bossDescriptionString.Length; i++){
    8.             if(String.Compare(""+bossDescriptionString[i], "\n") == 0){
    9.                bossDescriptionText.text += "\n";
    10.             } else {
    11.                if(i < currentCharacter){
    12.                   if(String.Compare(""+bossDescriptionString[i], "-") == 0){
    13.                      bossDescriptionText.text += "_";
    14.                   } else {
    15.                      bossDescriptionText.text += bossDescriptionString[i];
    16.                   }
    17.             } else {
    18.                bossDescriptionText.text += " ";
    19.             }
    20.          }
    21.       }
    22.    }
    23. }
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
  3. LilFire

    LilFire

    Joined:
    Jul 11, 2017
    Posts:
    74
    It seems like you do heavy String concatenation etc...
    String is a reference type. Being a reference types implies, that the value of a string variable is NOT the actual data, but a pointer/reference to the actual data.
    Also a String is immutable, which means the state of a string can't be changed after it has been created.
    Every time you append a string to another, you allocate a new memory space for this new string, and copy the result in this space. The allocation operation is expansive, and if you do it in a loop, like you are doing, it's slow.

    You can check at StringBuilder to solve this problem.
     
  4. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Oh. Huh. Thank you. For some reason I thought the Profiler was Pro-only.



    If I'm reading this thing right, it looks like it's actually the UI that's bogging things down, not the script. Does anyone know what I can do about that?

    EDIT: Turns out I had not one but two outlines on the updating text. I have no idea when that happened or why. A single outline only causes like 1/10th the lag of two.

    Thanks for your help. Sorry the code wasn't the answer.
     
  5. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    What is the point of this?
    Code (csharp):
    1. if(String.Compare(""+bossDescriptionString[i], "\n") == 0){
    It looks like you are allocating a string just so that you can compare a single character? You can compare the characters directly.

    Code (csharp):
    1. if(bossDescriptionString[i] == '\n'){
     
    Owen-Reynolds likes this.
  6. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Oh. I didn't know how to do a char literal. Thank you! :D
     
  7. newjerseyrunner

    newjerseyrunner

    Joined:
    Jul 20, 2017
    Posts:
    966
    I got two ideas, both are just theories. You said your profile showed the UI was lagging. Well I see several possible reasons that could be.

    First, look at the number of times that you are updating bossDescriptionText.text. I don't know what type of object bossDescriptionText is, but I'm betting it's doing more than simply concatenating the string. Remember that calling a member on an object is actually calling a get() method for said member and changing it calls a set(). Both can do more than just you think they are. Try creating your own string, building that, then setting bossDescriptionText.text = buffer at the end.

    Second, what happens if you move bossDescriptionText.enabled = true; to the end? That may affect what it's doing when you set the text. I've noticed lots of Unity modules behave differently depending on whether or not their enabled.
     
    Kurt-Dekker likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    @newjerseyrunner makes a lot of good points above: merely setting the .text field in a UI Text object probably triggers a full rebuild of all the mesh data for that object, and that's expensive relative to just building string.

    Definitely keep the string just as a normal string until the last possible point, then move it into the UI Text object's .text property once.
     
  9. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Strongly consider switching to TextMeshPro for your text solutions. One of the example scenes is typewriter text that doesn't have a full mesh rebuild.
     
  10. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    That does sound pretty good. Even though, you know, removing the second outline fixed the problem. My own solution required a fixed-width font to even make spelling out centered text possible. (As you can see from the appended trailing spaces. I tried to figure out a way to do it with a non-fixed-width font and pure math but that quickly got confusing.)

    I'm a little confused as to whether or not Text Mesh Pro is free or intends to stay free or what the situation is with that?
     
  11. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    TMP was acquired by Unity and is available for download. There are links for the proper downloads in the UI forum. It's also in the package manager (I think), in 2018.
     
  12. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    @WarpZone Can you tick `Deep Profiler` and show the results? It will slow down even more, but show much more information.
     
  13. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Again, guys, I accidentally had two outline scripts attached to the same Text object. It was drawing outlines around my outlines. This caused the slowdown. It's much better now.

    I looked into TextMeshPro, and you guys were right, it's amazing. I can put my own textures on there!? Faux bold and italic!? Forced capitalization!? Underline and Strikethrough!? Even this forum doesn't support strikethrough! TextMeshPro does tricks I didn't even know I needed. It even renders properly in the viewport!

    I'll definitely be using it from now on and I'm confused as to why, after acquiring it, Unity Team didn't replace the default text solution with this. (Probably because someone would have to sit down and write out the documentation for it, huh?)

    I'm slightly disappointed that it wasn't able to center an arbitrarily-sized paragraph and then display that centered paragraph one character at a time. I'll still need to use the trailing spaces trick and a fixed-width font. But overall I love TextMeshPro's compelling feature set, and if it's also faster? Then that's just amazing.
     
    Last edited: May 9, 2018
  14. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    That's a real shame.

    Oh wait...
     
  15. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    *squints at formatting options*

    How'd you do that?
     
    Last edited: May 9, 2018
  16. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Not all of the valid tags have a button.

    [ s] [ /s] will produce strike through, like this
     
  17. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Sigh.

    Worst part is, there's room for two extra little buttons in the browser.
     
  18. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Unity's UI is really fast, as long as you don't touch it and it stays completely still and it doesn't have particularly many elements on it.

    So in the real world it's really slow.

    There's a good talk from Unite Europe 2017 that goes into the details, link here.
     
    Kiwasi likes this.
  19. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Although i've found some things to be outdated, for example Animators dont cause a redraw after the animation is finished.
     
  20. WarpZone

    WarpZone

    Joined:
    Oct 29, 2007
    Posts:
    326
    Are you saying it'll run fine when I test my game in Unity, but slow when I publish my game?

    If that's the case, what good is the profiler if it's just going to give you different results in Unity than in-game?

    Because right now when I test my game in Unity, it runs fine.
     
  21. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Always profile in game and on target hardware. Profiling in the editor is frequently misleading.
     
    Peter77 likes this.