Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Performance: Accessing variables from other classes continuously versus storing them.

Discussion in 'Scripting' started by Deleted User, Jan 14, 2015.

  1. Deleted User

    Deleted User

    Guest

    For example, always calling "transform.position" as opposed to "Vector3 pos = transform.position" then calling pos.

    Which is more efficient?
     
  2. Kirk Clawson

    Kirk Clawson

    Joined:
    Nov 4, 2014
    Posts:
    65
    In the .net world, the unwritten rule (actually it may be written - I just don't know where) is that accessing a property or field (transform.position) is trivial, so you don't need to cache the result. Accessing a method (anything with parenthesis after it, something like transform.GetChild(0)) might have performance implications and could warrant caching locally if you have to use the result multiple times.

    Of course, the compiler doesn't enforce this, so it's trivially easy to violate this rule. I've seen it in bad production code where an expensive database call is executed in the getter of a property. Assuming that the Unity team didn't do anything silly like that, I usually go with the rule of thumb:

    If it's a property or field, don't cache. If it's a method result, cache (if using multiple times).

    Sometimes I'll cache a property or field if it's two or three fields/properties deep (object.propA.fieldB) just to save on some typing, though.
     
    Deleted User likes this.
  3. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Though I would recommend to cache anything that requires GetComponent
     
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Unity did do something silly. .transform, .rigidbody, .camera, and all of those other helper properties are really hiding a call to GetComponent. GetComponent is not cheap. So grabbing the individual values is trivial, but grabbing the components itself can be expensive. If you need the same component multiple times a frame then cache the reference.

    The hope is that this will be fixed in Unity 5.
     
    Deleted User likes this.
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    In the case of transform, GetComponent is only used on the first call to the property when the backing field is null - which makes sense because a GameObject can't exist without a Transform whereas it could gain or lose other components throughout its lifecycle.
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Are you sure? If this is the case then go ahead and used .transform. My understanding was this was planned, but not yet introduced. I could be totally wrong.
     
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Pretty sure.

    That being said - someone did do a benchmark sometime ago and found that accessing a cached reference to transform was faster than hitting the property directly. So if you're using it a lot then, for the time being, it seems to make sense to still cache it. (We do)
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    Well, all the helper properties are eliminated (except for transform), so yes I guess that's "fixed". ;) And yes manually caching transform is still faster, last I checked. It's really only a concern if you access it a lot though (and "a lot" means way more than just a few times per frame).

    --Eric
     
  9. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    I'm actually kinda glad they are removed in 5 since I can just cache my own that way, and not have to worry about my name clashing with the transform provided by the monobehaviouer
     
  10. Zaladur

    Zaladur

    Joined:
    Oct 20, 2012
    Posts:
    392
    The 'transform' property is staying around, its only all the other ones that are leaving.
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,398
    For sure removing them was the right move, since it was always seemingly random which components got shortcuts and which didn't. It also seemed to make people unclear on how Unity actually works, but if you have to use GetComponent for everything except Transform, then that should help clarify the component architecture.

    --Eric
     
  12. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Ya well even with transform things are a little different now anyways since we got 2 different kinds of transform now.
     
  13. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's a good point actually. I wonder how Unity guarantees that GetComponent<Transform> doesn't return a RectTransform accidentally.
     
  14. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Well they are 2 different types, from what I seen you have to explicty getcomponent the RectTransform. Just using go.transform won't get it.
     
  15. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    It's OOP. A RectTransform is a Transform.

    I think the main benefit of removing them was reducing dependencies inside the engine. It allows smaller builds for platforms where this really matters, like webGL. If you don't use anything from the physics engine, the physics engine won't be added to your build.
     
  16. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Not necessarily. Because a RectTransform is a Transform and therefore fulfills the generic type check.

    What I said seems silly in retrospect. I didn't realize the two components were mutually exclusive. (I haven't used the new UI yet).

    That being said - does the transform property give you back the RectTransform for GameObjects that have it?
     
  17. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    This gets you the RectTransform. The RectTransform inherits from Transform. Its basic OOP and polymorphism

    Code (CSharp):
    1. RectTransform myRectTransform = (RectTransform)transform;
     
  18. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Yeah - I know how inheritance works :)

    I was asking if this is how the property actually behaved because it's not explicitly documented as such. And oddly enough, the documentation caveats with "or null if none is attached" which is actually impossible...
     
    Kiwasi likes this.
  19. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    And to take it even one step further. Since Transform implements IEnumerable consider:

    Code (csharp):
    1.  
    2. foreach (Transform t in transform)
    3. {
    4.     // could t be a RectTransform?
    5. }
    6.  
    Subsequently - does it have any impact on Transform.GetChild()?
     
  20. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Valid points. My exploration so far indicates that it works exactly as the inheritance structure would lead you to believe. GetChild, enumeration and so forth will all return Transfroms for both Transforms and RectTransforms. You can treat these a Transforms without any issues, or cast them to RectTransforms.

    4.6 does suffer from significant lack of effort on the documentation side.