Search Unity

OnGUI() optimization: stack, struct, value-types and Rect.

Discussion in 'Scripting' started by by0log1c, Feb 23, 2012.

  1. by0log1c

    by0log1c

    Joined:
    Jan 30, 2011
    Posts:
    40
    Hey there. I'm just starting to work on yet another GUI, using the OnGUI() approach, and I'm trying to optimize it as much as possible; the ones I wrote tend to be quite costly. I'm now trying to really understand how memory works so please correct me where I'm wrong.

    I used to declare all my Rect within the OnGUI() method and I suspected this was a problem but then I realized they are struct. From what I understand, struct are value-types so they live on the stack. Declaring them within a method has very little impact since the stack will be released when the method exit and it is not garbage-collected. The GC is usually the true problem related to memory allocation.

    That would mean that creating Rect within OnGUI() is fine and I can stop figuring workarounds with the ref keyword or List<Rect>(), correct? :confused:

    Do you guys know of any performance pitfall or do you have any neat tricks when scripting complex GUIs? :D
     
  2. npsf3000

    npsf3000

    Joined:
    Sep 19, 2010
    Posts:
    3,830
    I think that the OnGUI is known for so many performance issues, the creation of a new Rect is too tiny to worry about.

    I recently moved to a lambda based system - but that's because of some very specific issues - the adding and removing of Gui items form the OnGUI function. I think moving to nGUI or similar is going to be my next step.
     
  3. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    If you want to optimize your OnGUI usage, working and opting the events is the first and primary step. Everything else will only be a fraction of it (beside usage of strings that go to autogarbage, thats a fat no go if avoidable)

    If you want to switch to another more complex system, I personally would go with EZGUI or GUIX
     
  4. by0log1c

    by0log1c

    Joined:
    Jan 30, 2011
    Posts:
    40
    Thanks for the feedback. I would probably avoid going with an external package if I can avoid it, but I'll definitly note your suggestions if I change my mind.

    Dreamora, by 'working and opting the events' do you mean 'make sure everything that's called is necessary'? I already do my best to control my GUI flow as tightly as possible but I hope there was something more I could do.

    About strings, I figure using StringBuilder is something I should definitly consider yet I'd still like to understand: if I write something like:
    Code (csharp):
    1. void OnGUI()
    2. {
    3.     GUI.Label(new Rect(0,0,Screen.width,Screen.height), "Constant Text");
    4. }
    "Constant Text" is created within a method so I figured it lives on the stack, even though its a reference. I'm now guessing a new string object is created on the heap on every draw and the reference to it is what goes in the stack, hence killing the GC(), am I correct? :confused:

    Would declaring that same "Constant Text" outside the method results in performance gain? What if I made the string variable static? What if I made the string variable const? :confused:

    I'm trying to optimize GUI, but the big picture is that I want to understand memory management within the CLR.

    Thanks again, your help is very appreciated!
     
  5. tonyd

    tonyd

    Joined:
    Jun 2, 2009
    Posts:
    1,224
    You want to have little or no game logic in OnGUI, as it gets called twice per frame.
    Avoid adding strings, use String.Format or StringBuilder instead.

    But the built-in GUI performance isn't THAT bad. My last game was 100% GUI and still ran at around 30 fps, even on iPad.
     
  6. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Also note that for the sake of usability and to ensure maintainable code, you want to avoid "magic strings" and other values in the first place. These should almost always be a member variable stored in the/a class, and not created in the method call. There are always exceptions, but that's the general rule.

    -Jeremy