Search Unity

Alternative to Object.name?

Discussion in 'Scripting' started by McMayhem, Oct 9, 2015.

  1. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    So I'm currently trying to rigorously lessen the garbage collector memory allocation for my game. I'm down to about < 200 bites, but I think I can do better. Something I noticed in the profiler:


    Getting a GameObject/Transform/etc's name using the object.name method allocates a small (but potentially problematic) amount of memory each time it is called.

    I know there are ways to get around string comparisons causing allocation using the Compare method. Is there a similar workaround to get an objects name without having to allocate the memory?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    What are you using the 'name' property for?

    I can't think of anywhere I use the 'name' property in my games except for editor script things (and those I don't care about GC, they won't be in build).

    You should probably be able to perform whatever task you're using 'name' for in some other way.



    Also, what are 'bites'.

    a byte is 8 bits, and a bit is... well a single binary value (0 or 1). Not sure what 'bites' are. :p
     
    Kiwasi likes this.
  3. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    I use an object's name for various purposes. One of the main ones is if an error occurs and I need to know which object it came from. That allows me to shorten my search pretty quickly.

    It should be noted that here, I'm using AnimationClip.name. I use that because I need to pass a string to animation[curClip.name].

    Yes, you've discovered a typo! I tend to do this quite a lot with English words that sound exactly the same, such as "weather" and "whether" or "whole" and "hole."

    Thankfully, I'm quite familiar with the concept of bits and bytes.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    In the case of error checking, I'd wrap that in a compiler condition of "UNITY_EDITOR". You'll still get the garbage at editor time, because you need the error tracking. But after build, the error checking isn't needed, use the debug build for that. So you don't need to be pulling that property anymore.

    Cache the name at start. It isn't garbage if you store it and use it. It's only garbage when you orphan it.

    Don't worry dude, it was a joke.
     
  5. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    The problem with that is players can generate their own content for the game. These bug logs need to be as verbose and specific as possible so that one can locate the source of an issue. Regardless of whether its a debug build or not, there still has to be a way to catch where errors are occurring.

    Again, there's the added issue of player generated content. The animation list is modular and thus caching the name at start wouldn't do any good since there's no way to know what to cache.

    I'm not your dude, guy.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Wow bro, talk about testy.

    Would have loved to help you, as I have ideas to deal with your issues, but eh.

    Peace.
     
  7. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    I was acknowledging your joke, by throwing in one of my own. I figured it would be obvious considering literally nothing else in the post was an attack.

    It's from SouthPark.
     
    ilmario likes this.
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    Reasonable, text can be easily misconstrued, that's why I included the emoji in the first place.


    Anyways.

    You can cache that name the first time its accessed. You'll have to call name at some point, but only call it the first and only time.

    Code (csharp):
    1.  
    2. private string _cachedName;
    3.  
    4. void DoSomething()
    5. {
    6.     if(_cachedName == null) _cachedName = _clip.name;
    7.     animation.Play(_cachedName);
    8. }
    9.  
    Not necessarily at 'start', but at the first time. Like I said, its not garbage until you orphan it.



    As for the error logging, which you want at runtime as well. I'm assuming this means that you allow the player to create their own GameObjects and name them. Don't store that created name as the GameObjects name... store it in some custom field.

    Create a script like "UserGeneratedObject", plop that on the GameObject that was created at runtime by the user, and store any information related to the object for the player there. This way you can add stuff to it, like a history log and save information as well.


    See, the 'name' property from GameObject and AnimationClip are creating garbage every time you access it, because it is pulling those values from the C++ side of Unity. Because the name is coming out of unmanaged memory, into managed memory, a whole brand new string needs to be created. By storing it Mono/.Net side, you're avoiding creating it every single time you access it.
     
  9. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    The animation operates off of a custom class called MoveSet that has all of the movements and necessary animations for a given weapon. MoveSets are loaded from the StreamingAssets/Data/MoveSets/ folder and swapped in and out depending on the type of weapon that gets equipped. I guess I could create another custom class for moveset animations that have a clip and a name and then use that name to pass to the animation, but would that be the most efficient way to go about it?

    Code (CSharp):
    1. public class MoveSetAnim
    2. {
    3.     private string _clipName;
    4.     private AnimationClip _clip;
    5.  
    6.     public string ClipName
    7.     {
    8.         get { return _clipName; }
    9.         set { _clipName = value; }
    10.     }
    11.     public AnimationClip Clip
    12.     {
    13.         get { return _clip; }
    14.         set { _clip = value; }
    15.     }
    16.  
    17.     public MoveSetAnim(string name, AnimationClip clip)
    18.     {
    19.         _clipName = name;
    20.         _clip = clip;
    21.     }
    22. }
    Maybe that would be easier in the end run.

    I was going to poke fun at your use of the word "Testy" too, but I figured if you didn't know I was joking before, you likely wouldn't appreciate it all that much.
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I personally wouldn't worry about GC allocation for error handling. The game is not in it's correct state anyway, so performance isn't your key concern. Not having the error is your key concern.
     
  11. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    How much allocation is too much, though? If I'm deploying for the PC platform, what range of b/kb/mb am I looking to stay in for max allocation at any one point?
     
  12. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    Too much if is you've got noticeable frame losses due to the GC running.

    One of the most usefull advices in any software development is to not optimize before you need to. Write code that's easy to read and easy to maintain, and optimize when you have to.

    I mean, obviously don't write n! search algorithms, and pick up patterns that's going to help you down the line (like caching references instead of doing GetComponent everywhere). Other than that, don't worry before you have to.

    To be able to put out optimization until it's needed, you really have to write somewhat decoupled code - if some class or method is dependent on the implementation of another class or method, optimizing it later on becomes very hard.
     
    McMayhem and Kiwasi like this.
  13. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    That's fantastic advice.