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

Alternative to Object.find

Discussion in 'Scripting' started by Jason210, Feb 10, 2015.

  1. Jason210

    Jason210

    Joined:
    Oct 14, 2012
    Posts:
    128
    Was discussing on YouTubehow Object.find / Get.component method is not very efficient because everytime you use it Unity has to parse ever object name in the game. Someone partially explained a better way:

    "better way is to keep track of every dynamic object you track, and to pass their "managers" or parent class as an argument on initialization. That way, your manager class can keep a list of your units for exemple and remove the ones you dont need. Units keep a ref to their manager and they communicate with it."​

    If someone here knows what he was on about I'd really appreciate some help in clarifying it, and also an example.
     
  2. shaderop

    shaderop

    Joined:
    Nov 24, 2010
    Posts:
    942
    He's just saying that you could have a collection somewhere that stores all instances of a given MonoBehaviour. That way when you need to access said instances, you can just iterate through the collection instead of using Find. And it's Find that is the most expensive performance–wise. GetComponent is rather benign in comparison.

    Here's a very simple example:

    Code (csharp):
    1. using System.Collection.Generics;
    2.  
    3. public class Foo : MonoBehaviour
    4. {
    5.   public static List<Foo> Instances = new List<Foo>();
    6.  
    7.   private void Awake()
    8.   {
    9.     Instances.Add(this);
    10.   }
    11.   private void OnDestroy()
    12.   {
    13.     Instances.Remove(this);
    14.   }
    15.  
    16.   public void DoStuff()
    17.   {
    18.     // Do something that "[builds] on feelings and emotions untapped so far."
    19.   }
    20. }
    21.  
    That's it. Now every instance of Foo will be stored in the static field Instances. Another MonoBehaviour can access those instances like so:

    Code (csharp):
    1. public class Bar : MonoBehaviour
    2. {
    3.   private void Update()
    4.   {
    5.     foreach (var foo in Foo.Instances)
    6.     {
    7.       foo.DoStuff();
    8.     }
    9.   }
    10. }
    11.  
    No need to call Find or GetComponent. You can opt for a fancier solution, like having a separate manager MonoBehaviour that stores all the instances instead of having them stored in a static field. Or you can use a dictionary instead of a list to associate those instances with names. But that the gist of it.

    HTH

    Anyone feeling the Peter Molyneux reference above?
     
    Jason210 likes this.
  3. Glockenbeat

    Glockenbeat

    Joined:
    Apr 24, 2012
    Posts:
    669
    As always it depends on what you are going to do and what you want to achieve. If there are dozens of objects which you need access to at runtime, possibly each (x) frame(s) it might be a good idea to cache them in Start() or Awake() just to have them ready when needed. However there is only little sense in doing that for objects you need to address only once in a while. In that case it might be a better approach to just get a reference once needed and cache it then.

    As of getting a reference.
    GetComponent is not that bad if used right. First of all: NEVER use string search. That is bad, and you should feel bad. ;)
    This applies to any method, may it be Find(), GetComponent(string), FindGameObjectsWithTag() and alike. If possible always use the generic version instead. Then cache the result.

    There is a nice talk from Unite 2007 showing some of the principle, including the instance caching mentioned by shaderop:


    edit: The part I'm talking about is at around 40 minutes.
     
    Last edited: Feb 10, 2015
    Jason210 likes this.
  4. Jason210

    Jason210

    Joined:
    Oct 14, 2012
    Posts:
    128
    Hi

    Great explanation Shaderop - exactly what I was looking for. Thanks for that!

    I don't know whether caching would be necessary or not. The project is a simulation of a steam power plant (or heat balance system) where there are several heat engines all connected to the same steam supply. An increase or decrease in steam pressure (and other properties) will affect every machine in the system, and machines themselves will then affect other systems they interact with. Therefore they will be referenced continuously.

    /Jason
     
  5. Glockenbeat

    Glockenbeat

    Joined:
    Apr 24, 2012
    Posts:
    669
    Then you should cache. ;)
     
  6. Jason210

    Jason210

    Joined:
    Oct 14, 2012
    Posts:
    128
    I guessed you'd say that :)

    Thanks man!