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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How important is efficent code?

Discussion in 'Scripting' started by AntikytheraMachines, Jul 24, 2015.

  1. AntikytheraMachines

    AntikytheraMachines

    Joined:
    Jun 23, 2015
    Posts:
    1
    void Awake()
    {
    mazePrefab = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ().mazePrefab;
    playerPrefab = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ().playerPrefab;
    destinationPrefab = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ().destinationPrefab;
    spotLight = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ().spotLight;​
    }

    VS

    void Awake()
    {
    levelDesignObject = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ();
    mazePrefab = levelDesignObject.mazePrefab;
    playerPrefab = levelDesignObject.playerPrefab;
    destinationPrefab = levelDesignObject.destinationPrefab;
    spotLight = levelDesignObject.spotLight;​
    }

    how resource intensive are 'Find()' and 'GetComponent()' ? does calling them multiple times have performance considerations?
     
  2. Duugu

    Duugu

    Joined:
    May 23, 2015
    Posts:
    241
    As this is Awake() you won't see any difference. (As long as you as you don't instantiating a regular and massiv amount of this object).

    It's not that find and getcomponent are breaking you game performance on every call. :) It's all about the fequency.
     
  3. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    It absolutely has performance considerations, but this is an Awake function, so unless it's being instantiated multiple times a second, there's a good chance those considerations are (in general) premature. If it were in the Update() function, that's a completely different story.

    That said, this example seems particularly offensive, and I think the only reason the second version would exist is due to intentionally trying to create efficiency problems. Make it a part of your normal routine to only use Find and GetComponent as few times as possible (making a temporary reference to the data it returns in situations like this one), but don't go out of your way to avoid the functions or anything, except in Update().
     
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Don't stress about performance until it starts to bite you.

    The second one will be slightly faster. But it requires implementing a singleton or static variables. Statics can mess with your code.
     
  5. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    The second example is more efficient in terms of performance and user typing, so I'm not even sure why you'd consider the first one.
     
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,533
    Reliable code is more important than efficient code. ("Efficient" code that crashes the game will give you an effective framerate of 0 fps.)

    In this method:
    Code (csharp):
    1. void Awake()
    2. {
    3.     levelDesignObject = GameObject.Find ("Level Designer").GetComponent<LevelDesign> ();
    4.     mazePrefab = levelDesignObject.mazePrefab;
    5.     playerPrefab = levelDesignObject.playerPrefab;
    6.     destinationPrefab = levelDesignObject.destinationPrefab;
    7.     spotLight = levelDesignObject.spotLight;
    8. }
    unless you're absolutely, positively 100% sure that you'll find a GameObject named "Level Designer", and that it definitely has a component named LevelDesign, Awake() could throw a NullReferenceException error, which means mazePrefab etc. may be unassigned, which will probably cause other methods to fail, too. What if someone renames "Level Designer" to "LevelDesigner", or moves the LevelDesign script to a child object?

    Be safe and check for null whenever you call Find() or GetComponent(). :)
     
  7. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    What do you suggest doing if one or more of these are null?
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,533
    Something appropriate. ;) (Add the missing GameObjects and/or components, or disable this MonoBehaviour, or assign default values, or whatever's a graceful way to handle it in context.)
     
  9. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    971
    Fair enough though there is not always an "appropriate" thing to do. I've seen code that looks like
    Code (csharp):
    1. try
    2. {
    3.   // ..
    4. }
    5. catch (NullReferenceException e)
    6. {
    7.   Log(e);
    8.   throw;
    9. }
    And I'm just not sure of the point.

    Is there is a way to ask Unity to shutdown if you hit an unrecoverable problem?
    Alternatively, is there a hook to do custom error handling on your MonoBehaviour code at a higher level?
     
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,533
    Agreed -- I don't see much of a point to that try..catch..throw block. On iOS, a NullReferenceException will usually cause an EXC_BAD_ACCESS crash before it catches and rethrows, and on most other platforms and the editor Unity will log the NullReferenceException anyway, with a stack trace to the culprit.

    You could always call Application.Quit() to shut down, but there's usually a graceful way to recover and continue running, even if it's a somewhat degraded mode.
     
    Yarbius and eisenpony like this.
  11. Yarbius

    Yarbius

    Joined:
    Apr 29, 2014
    Posts:
    22
    I cannot see why you would ever use a Try/Catch block when a simple null check would work. Throwing exceptions should be for truly exceptional circumstances and not to control regular program flow. I like John Skeets comment on Stack Overflow ... http://stackoverflow.com/a/161965/175107
    "Basically, exceptions shouldn't happen often unless you've got significant correctness issues, and if you've got significant correctness issues then performance isn't the biggest problem you face."