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

Is Get Component bad within Update?

Discussion in 'Scripting' started by IndieGameHustle, Apr 21, 2013.

Thread Status:
Not open for further replies.
  1. IndieGameHustle

    IndieGameHustle

    Joined:
    Jul 25, 2012
    Posts:
    65
    Hi,

    I am using "Get Component" to Access A Child Object Transform Direction in my Movement Script.

    My Question: Is this a wrong way of using it or will this cause issues later that I am not aware of?
     
  2. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Yes, this is awful. What you should do is store it in a variable in Start or Awake.

    ~lanDog
     
    ETGgames likes this.
  3. EliteMossy

    EliteMossy

    Joined:
    Dec 2, 2012
    Posts:
    513
    It is not always awful, sometime's it is avoidable. But you should cache it if you can, but like i said, not always possible.
     
    Benjami likes this.
  4. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,684
    I can not see any example when placing GetComponent in update is unavoidable. Cache it once, or as little as possible. It is a costly venture to the engine.
     
  5. EliteMossy

    EliteMossy

    Joined:
    Dec 2, 2012
    Posts:
    513
    How about a routine every so often to access a object you don't know about in advance?
     
    Benjami likes this.
  6. IndieGameHustle

    IndieGameHustle

    Joined:
    Jul 25, 2012
    Posts:
    65
    Ok,

    Well, Using get axis horizontal Vertical to move left and right does not seem to allow me to change the direction of the object without affecting the axis.

    So I used Get Component to Affect the childs direction while Crating and empty object to serve as the movement. I rather not do that.

    But I do understand the concern. I should prob. only use it in the Start function but not for movement needs since its being called often.

    I am sure it can be done but I just havnt found a way just yet. :)
     
  7. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,684
    @EliteMossy
    Well some routine, or inserting some type of breaker, if condition, such that you are not asking every frame to get component. That just seems like it would be a very chuggy engine.not to mention puzzling as why would any one use get component every frame. Seems like a terrible architecture.
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's not "awful"; it's unlikely to make any difference if you're just accessing something once per frame (though it doesn't hurt either of course). It's more important to cache the GetComponent calls if you're using lots of components or accessing them in a tight loop. Just make sure not to use strings with GetComponent.

    --Eric
     
  9. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Interesting, I'm in a situation now where I use it, and was wondering about its performance.
    My question is:
    If you have hundreds of objects in the scene, and want to cache multiple child transforms for each (let's say there could be 10), wouldn't that hurt performance? You would have a script on each one. I'm talking about a situation where you only do a FindInComponent when you instantiate the item, NOT every update/frame.

    Basically, all if my item prefabs look like this:

    Iron_Knife
    InHand
    Knife
    OnGround

    All of the these are empty gameobjects, except for "Knife". It is the actual mesh, collider, etc.

    When the player drops this item on the ground, I move the Knife under the OnGround gameobject, and set its orientation to zero. This puts it at the proper rotation and placement for a knife lying on the ground...laying on its side, resting on the top.

    When the player equips the Iron_Knife, I move the Knife under the InHand empty gameobject, and reset its orientation, position, etc to 0. This puts it at the proper rotation and placement for a knife in someone's hand. Pointing forward, at the right rotation.

    Ok...so when I do this, I get the desired placement "InHand", "OnGround", find the gameobject with that name under the top gameobject, and put the Knife under it. I have to use a Find for this. As you can imagine, I don't have to do this very often..only when the item gets picked up, equipped, etc.

    Sorry this is dragging on. Here's my point/question:

    For every single thing I place in the world, the top level gameobject would have to have a script with variables that I could access. Granted...there would be no update statement, but still...seems like it would hurt performance?
     
  10. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Awful was a bad term and I take it back. More like you should avoid this if possible.

    ~lanDog
     
    david-mal likes this.
  11. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    IMO, the only things that should be coded into an Update are:

    1. Movement/Rotation
    2. Input

    All the rest should be in InvokeRepeated functions, or be event driven.

    I see no reason to ever put a GetComponent into update.
     
    ROBYER1 likes this.
  12. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,684
    I have just discovered while() and do as coroutine and will be implementing them to move my parallax backgrounds. The benifit in my case is... I have a side scroller with dozens of background groups. Each group will have at least 3 planes. Traditionally, I would place an update on each, and just have a condition, to return if false. However, with while() I can perform the function just the same. The benifit is that by not using update, I am saving the engine from running a couple of dozen updates. Even tho, most are not doing anything and instantly return they still have to enter update and return. While() prevents this. I think it will help the engine.
     
  13. IndieGameHustle

    IndieGameHustle

    Joined:
    Jul 25, 2012
    Posts:
    65
    I am very happy to see everyone chime in on this.
    So I will just remove the get component call I made and rethink it.

    I am using GetAxisRaw Horizontal and Vertical to have movement.

    Code (csharp):
    1.  
    2.  
    3. //Left
    4.         else if (Input.GetAxisRaw("Horizontal") < 0)
    5.         {
    6.        
    7.             boxPlayer.eulerAngles = new Vector3(transform.eulerAngles.x * Time.deltaTime, -90f, 0f);
    8.            
    9.         }
    10.  
    I am just happy that I asked the question before moving on to my next goal to complete.

    I just need to change the direction of the Cube without changing the Axis.
     
  14. RSG

    RSG

    Joined:
    Feb 20, 2013
    Posts:
    93
    I don’t know if this would help you out but normally when I have to manage tons of objects I use a list or dictionary. Rather than attaching a script to each object created, I record a reference to that object on a list after it is instantiated. I use a dictionary when I need to differentiate between the objects. Searching a dictionary uses less resources and is faster than doing a find. Hope that helps
     
    Last edited: Apr 22, 2013
  15. BlackMantis

    BlackMantis

    Joined:
    Feb 7, 2010
    Posts:
    1,475
    Clever method. I use the same sometimes.

    Event/Routine referencing is the way to go. In some cases if the player was destroyed, and spawned again during runTime I will ask in runTime if the target Obj is null or not.

    Code (csharp):
    1.  
    2. var playerObj : GameObject;
    3. var playerScript : MonoBehaviour;
    4.  
    5. function Update() {
    6.     //------------//
    7.     if(playerObj) { } // Do nothing if we have a reference
    8.     else {
    9.       if(GameObject.FindWithTag("Player")) {
    10.         playerObj = GameObject.FindWithTag("Player");
    11.         if(playerObj) {
    12.           playerScript = playerObj.GetComponent(playerScript);
    13.         }
    14.       }
    15.       else {
    16.         Debug.LogError(name + " Can't Find A PlayerObj");
    17.       }
    18.     }
    19.     //------------//
    20. }
    21.  
    I'm sure I can ask in a routine/Event and save a little performance during the Object hunt.

    Is this way bad or what?
     
  16. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    2,511
    Sorry to tag along the old thread, but I have been thinking about caching the master component (the one that contains the reference to all other components) of the enemy unit in the beginning of level load (into a list), and then access them somehow during game play.

    The idea is to be able to have access to say a enemy unit 01 when it collides with some trigger (say result of a OverlapSphere). When my enemy AI casts a overlap sphere to get array of hit colliders I need to find out which element of my cached components I need to access. All I get is return of collider so from there I can get a game object. But that is where I am stuck.

    Is there some good way to find the cached component from the gameobject? How would I know? How would I link the game object with the component that is cached somewhere.

    I can probably go through in loop to check if cached component's game object is the one that I am looking for. But this can't be very efficient.
     
  17. sluice

    sluice

    Joined:
    Jan 31, 2014
    Posts:
    416
    The only time I will occasionally call GetComponent outside of the scene initialization is after a collision/trigger check, when you you multiple targets and you have no way of knowing in advance which one you will collide with.

    Code (CSharp):
    1.  
    2. void OnTriggerEnter(Collider other)
    3. {
    4.     if(other.tag == "Enemy")
    5.     {
    6.         other.GetComponent<EnemyScript>().DoSomething();
    7.     }
    8. }
    9.  

    In all other cases, I cache my GetComponent calls.
     
    ROBYER1 likes this.
  18. LOSTSOUL86

    LOSTSOUL86

    Joined:
    Apr 17, 2017
    Posts:
    10
    Bit old post but ... what if I hit a gameObject with a raycast.
    Then I need to run the script withing the object but all I have is just the gameObject reference or name...
    To run the script in this gameObject I need to use getComponent?
    If I have many possible objects being hit with the raycast, if I build an array of the object references to this script I need to search trough them to see which one got hit by name?

    With all respect I think the use of getComponent is unavoidable with raycast in Unity?
    Unless there is something I dont know...
    Using sendMessage is I think slower than getComponent...
    So how I can avoid to use getComponent every frame if hitting with raycast?
    At least if I can extract the object index in the array from this raycast I could maybe build an array of the scripts...
     
  19. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Please don't necro-post to ten year old threads. As per forum rules, start your own post... it's FREE!

    When you post, here is how to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, log output, variable values, and especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)

    If you post a code snippet, ALWAYS USE CODE TAGS:

    How to use code tags: https://forum.unity.com/threads/using-code-tags-properly.143875/

    DO NOT OPTIMIZE "JUST BECAUSE..." If you don't have a problem, DO NOT OPTIMIZE!

    If you DO have a problem, there is only ONE way to find out. Always start by using the profiler:

    Window -> Analysis -> Profiler

    Failure to use the profiler first means you're just guessing, making a mess of your code for no good reason.

    Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

    https://forum.unity.com/threads/is-...ng-square-roots-in-2021.1111063/#post-7148770

    Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

    Notes on optimizing UnityEngine.UI setups:

    https://forum.unity.com/threads/how...form-data-into-an-array.1134520/#post-7289413

    At a minimum you want to clearly understand what performance issues you are having:

    - running too slowly?
    - loading too slowly?
    - using too much runtime memory?
    - final bundle too large?
    - too much network traffic?
    - something else?

    If you are unable to engage the profiler, then your next solution is gross guessing changes, such as "reimport all textures as 32x32 tiny textures" or "replace some complex 3D objects with cubes/capsules" to try and figure out what is bogging you down.

    Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

    This sort of speculative optimization assumes you're properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.
     
Thread Status:
Not open for further replies.