Search Unity

Cache component lookups - on Inherited members too?!

Discussion in 'Scripting' started by vreference, Oct 25, 2011.

  1. vreference

    vreference

    Joined:
    Mar 22, 2011
    Posts:
    154
    I was digging around for something in the documentation - now I've forgotten what - and decided to read through this optimization article again. My jaw nearly dropped when I read the entry below. I've always cached GetComponent results for anything that is used frequently... and the code I have runs pretty well on mobiles but I'm not done yet and I need every clock I can get... That "accessor variable" part and the example they use made my blood run cold. The example they give (transform) is labeled as an "Inherited Member" and I use these things constantly... gameObject and transform especially. Seriously? these aren't cached already?! There are warnings all over GetComponent not to use it in every frame so I assume using these variables must not be as costly as getComponent so what's the deal? Surely they wouldn't have taken the time to mention it in a list of only 5 things to look out for if it wasn't important?

    It's certainly not the end of the world... I can just replace all in all of my scripts and have my code "optimized" in a few minutes but... I was just hoping there was some mistake. I suppose I'll have to do some testing if no one has an answer.

     
    Hunter_Bobeck likes this.
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Correct, transform.position is essentially just a shortcut for GetComponent(Transform).position.

    I don't think so--GetComponent isn't that slow. The example code in the docs uses GetComponent in Update. It's highly unlikely that using GetComponent every frame vs. caching it will make any noticeable difference--if you're looping through hundreds of component calls per frame, then yes, do cache it, but if it's just one call it's probably not worth the extra memory usage. The optimization section says that in so many words: "not always worth it."

    --Eric
     
  3. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    Just add a middle class between MonoBehaviour and your component classes that has this:

    Code (csharp):
    1.  
    2.         Dictionary<Type, Component> componentCache = new Dictionary<Type, Component>();
    3.    
    4.     public Component GetCachedComponent(Type type)
    5.     {
    6.         Component result = null;
    7.         componentCache.TryGetValue(type, out result);
    8.         return result ?? (componentCache[type] = GetComponent(type));
    9.     }
    10.    
    11.     public T GetCachedComponent<T>() where T : Component
    12.     {
    13.         return (T)GetCachedComponent(typeof(T));
    14.     }
    15.  
    Then you can use GetCachedComponent and have it automatically cache all component requests.
     
    Hunter_Bobeck likes this.
  4. fanjules

    fanjules

    Joined:
    Nov 9, 2011
    Posts:
    167
    My jaw did drop. As a new user it doesn't inspire much confidence when I saw that. Why do they not make "transform" store the result of getcomponent() instead of being what appears to be a function/method which simply goes onto call getcomponent() ...in fact you have to wonder if it's not slower than doing a straight getcomponent()!

    I don't care if you can write a little bit of extra code to sort that... you shouldn't have to. Nor am I interested if getcomponent() "isn't that slow", calling a function which in turn then has to work though a list of objects to find a match by comparison is endlessly slower than a straight reference. This is basic stuff. Am genuinely curious why they have implemented .transform and so on like that. There has to be a reason...?

    I am not knocking Unity but as a new user I want to understand why they decided to implement the "shortcuts" like that. What am I missing? "It doesn't really matter most of the time" and "you can't write your own work around" are not answers.
     
    Hunter_Bobeck likes this.