Search Unity

use strings on Start()

Discussion in 'Scripting' started by Hagen, Aug 20, 2016.

  1. Hagen

    Hagen

    Joined:
    Aug 16, 2014
    Posts:
    36
    Hi, I have a lot of statements like this in my scripts, in the Start() mono behavior:

    string path = transform.parent.name + "/" + name + "/lbZCount";
    GameObject tmp = GameObject.Find(path);

    these are basically references to children objects and they are being identifed by the gameobject name

    Is this a heap consumer/eater? Or is it OK from the memory optimization standpoint?
     
  2. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    GameObject.Find() is a CPU consumer. The more objects you have in hierarchy the worse. It is more optimal to declare child objects as public GameObject's, and then assign them in Inspector window.
     
  3. lloydsummers

    lloydsummers

    Joined:
    May 17, 2013
    Posts:
    359
    Regarding heap though, you should be fine generally speaking. But there are a lot of factors.

    Yes, strings are brutal for heap - just look to Arduino where on a standard Uno you can't really have more than a few phrases or you will run out of memory. If you are working with WebGL, and creating thousands of game objects - those strings will eat up your memory (although, technically, I don't think it would be part of the Heap per-say, because it is being added after execution).

    When I was still working at a medical company doing WebGL with Unity, strings were the number one cause of out-of-memory errors, especially with earlier versions of Unity and iterations. This was not an issue in WebPlayer, and definitely not an issue for stand-alone application.

    We typically had less than 5,000 objects in the scene though. So even though objects had long JSON data blobs and URI's such as Bracket/11-15/SL --- that didn't really cause issues. It was more related to iterating through large volumes of strings (i.e. JSON to String manipulation) with deeply nested JSON structures (because Unity WebGL does not release memory references until the function has completely terminated).

    If that helps? Anything that supports Unity3D, should be able to hold simple string references just fine. But avoid them if you don't need them.

    Also, instead of GameObject.Find(...) -> use a registration system. I usually have a static holder that acts as a single point of registry. Every element that is created or destroyed registers itself to the registration. Why? You can pop things in and out of that registry as you need, so if you want something to "temporarily" be inaccessible, but to physically exist (think - object fading out of existance. It should have no properties, but needs to be visible) then you can just yank it out of the references.

    It also goes faster than GameObject.Find, which will iterate through every game object in the scene - even things you don't care or need to track. And with a registry, you can leverage LinQ. With a more complex class system, it means you can filter a list of all objects by a sub-type, and a position in space etc. But that's just my preference. Sorry for the rant!
     
  4. NoBrainer-David

    NoBrainer-David

    Joined:
    Jan 5, 2014
    Posts:
    34
    Did you have a lot of string variables that were identical? Do you know, if a WebGL build still has the ability to use string interning?
     
  5. lloydsummers

    lloydsummers

    Joined:
    May 17, 2013
    Posts:
    359
    Good question we had a lot of strings that were not identical. The entire application operated as a chart, and so massive amounts of JSON information would be sent in, and the scene structured on that.

    It included everything from positional, to naming, to text formating to template name and detail information.

    For any variables that were identical, we utilized flyweight pattern. Which is kind of string interning taken up a notch.

    We never really had a problem with strings in this way, it was recursive and iterative functions working with strings including Unity type conversions. For example .ToList() creates a complete duplicate set of data and it gets held until the original function that called it is complete. So doing some iterative work with conversions on larger data sets would very easily fill up your RAM.

    Plus earlier Unity versions had additional bugs with releasing memory from strings, making it only a matter of time until you hit out of memory.
     
    NoBrainer-David likes this.
  6. NoBrainer-David

    NoBrainer-David

    Joined:
    Jan 5, 2014
    Posts:
    34
    Interesting. Thanks for the insight!
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You do have to ask, why are you accessing the children objects this way?

    It won't be that big of a deal for GC or memory, not unless you create many of these objects each frame. But it does introduce the possibility of bugs.
     
  8. game_buddy

    game_buddy

    Joined:
    Sep 8, 2016
    Posts:
    9
    Hey,

    Might be too late, but following may help...

    If you are concatenating strings, since these are stored in the heap, you may, instead of adding them using the operator +, you could use instead System.Text.StringBuilder. Because strings are “immutable”, in other terms, you can’t change the content of a string without creating a new string object, you may instead use StringBuilder, which represents a mutable string of character; in other word, a string of characters that can be changed overtime. This means that memory will be allocated when the object is created, but no additional allocation will be required as the string is modified.

    As to the use of GameObject.Find, i would agree with zeflis; the less often the better :)

    Hope this helps.