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

GameObject.Find() question.

Discussion in 'Scripting' started by larswik, Nov 7, 2017.

  1. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    Had a quick question. I know the Find() option can be expensive and have been warned to stay away from it, use tags instead. But If you provide a path in find is it any quicker?

    GameObject.Find("foo"); vs. GameObject.Find("parent/child/foo"); ?

    Thanks.
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    Doesn't matter, don't use it either way. Optimizing for speed within GameObject.Find is like rearranging deck chairs on the Titanic. It's going to be slow no matter what you do. Worse, speed is just one reason not to use GameObject.Find. The linked article lists a number of better ways to get references to objects.
     
    Last edited: Nov 7, 2017
    Joe-Censored likes this.
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    The answer to all Find() questions is to search for your gameobject using a different method. It doesn't matter how you phrase the question.
     
    larswik likes this.
  4. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    Gotcha, thanks.
     
  5. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    Funnily enough, I think GameObject.Find("parent/child/foo") would actually be a worse solution because if one day you decided to reorganize your structure... oops, you just broke your script(s).
     
    larswik likes this.
  6. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    Why do you need it, if the objects your want to reference exist at edit time, just use SerializeField and assign the references in the inspector. If you create them at runtime just hold onto the reference after you create the object.
     
  7. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You can find all objects in the scene within Start, then add them to a dictionary for super quick look up or just add the ones you're interested in.

    Anything you make during gameplay, or destroy can also be tracked easily, just do the work up front then maintaining it is trivial.
     
  8. UziMonkey

    UziMonkey

    Joined:
    Nov 7, 2012
    Posts:
    206
    Not only is it inefficient, I also consider it a code smell. It you find yourself using it, there is almost certainly a better way of doing whatever it is you're doing.

    Normally when I find myself using it, I'm really trying to implement the service locator pattern and properly implementing it makes my code better and more resilient.
     
  9. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    @passerbycmc I will research this SerializeField. I have years of coding but this is my first game.

    @hippocoder That's interesting. So by adding references to all of the GO as the game starts to a Dictionary sounds interesting. If I make that Dict Static I could easily reach it with any script that needs information on that object.

    @UziMonkey I try to write efficient code. I know from what I read that Find() is expensive. But I think when and where you use them matters. If the player is in a store buying items from his inventory then I would feel the expense of using the Find() would have a low impact on the game play. If there are lots of transforms happening, particles systems and craziness happening on the screen, I can see how taking time out for a Find() to scan the Hierarchy of a GO can be a negative. Which is why I asked the original question to see if I could reach what I needed directly with a path to what I need.

    Thanks for the help guys!
     
  10. UziMonkey

    UziMonkey

    Joined:
    Nov 7, 2012
    Posts:
    206
    My point here is there's a better way to do it. The store should have an inventory of the game object items that are for sale. You shouldn't be using GameObject.Find to find them, you should be implementing a proper API to access them. I this case, a Store class that lets you list and buy objects. I stand by what I said, in every instance of a GameObject.Find call I've always been able to identify a better way of doing something.

    For me it's less about the performance (which is not that bad as long as you're not calling it every frame) and more about the code smell.
     
  11. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    For me, the biggest issue is using strings to find anything. That's just opening yourself up to too many possibilities for bugs.

    You could promise yourself that you'll be super methodical and never ever accidentally pick a name that's already in use by another object.

    You could promise yourself that you'll never make typos.

    You could promise yourself that you'll never ever rename anything. Ever. Or if you were to rename anything, you'll fix all scripts that depend on that name.

    You could promise yourself that you'll maintain this level of discipline for the entire length of the project's lifetime. And even afterwards if you're planning to support it via patches, asset bundle DLCs, etc.

    If you have anyone else helping you on the project and have access to the code, the possibilities for bugs increase exponentially.

    It might be OK if it's just a small project and you're just experimenting and tinkering around. However, for a larger scale project that you intend to ship someday, it's just too unreliable an approach.

    Runtime bugs are just plain evil. If bugs are going to happen, you want to try to make sure they happen at compile time. At least that way you have a chance to fix them before you ship it and let your users run into bugs.
     
  12. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    its not only about the cost of it performance wise, it is just hard to maintain code that uses it, can make it harder to track down where something is referenced and is more prone to breaking then referencing stuff directly.
     
  13. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    I hear what your saying and I agree. I think the Dictionary mentioned above is genius but to take it a step further I am always using the Find to reach a component of the GO. If I can store a reference to the GO's component directly that would also save time.
     
  14. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    I agree for the most part. I had a simple typo the other day and took me for ever to find it since it happened only every now and then. The item I was trying to find was "castleLeft" and It was searching for "castleLEft".

    This is my first game, hopefully to be released come summer. I think instead of having to go back and rewrite much of the code, it is better to learn from mistakes and use new better coding practices in future projects.
     
  15. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    I am going to test out hipcoders idea about adding references to the GO in the Start(). more specifically the GO components that I need access to.
     
  16. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    @hippocoder This way seems Genius and works!

    Code (CSharp):
    1. public static Dictionary<string,Button> goDict;
    2. goDict.Add("fireButRef", fireButton.GetComponent<Button>());
    3. print("FireButton is: " + goDict["fireButRef"].interactable);
    fireButton is a public GameObject in my GameController script. But adding it to a Static Dictionary will allow all my instantiated objects a quick reference instead of the GO.Find(). on the fire button and digging down to the component to see if it is intractable or not. Love this approach!
     
  17. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    You seem to be dead-set on storing references via string. Yeah, if you need to do that, then the dictionary is the way to go. But I'm not seeing why that's a thing you'd actually need to do. You could simply have a "public static Button fireButRef;" and get the same functionality in game, except with more autocomplete, and compile-time errors rather than runtime errors. Unless actually accessing it specifically by string is useful to you.

    Also, in this use case, you should be aware of the generally good principle of not allowing your in-game objects to know about your game's UI. This is a little more advanced of a concept, but in general, your in-game objects should provide methods and members and callback delegates to be controlled, but all of the actual bridging code should come from the UI side to the in-game side. This helps you avoid code that's overly interdependent on each other. Imagine if you changed your control scheme or input method, and in the process deleted your existing UI code; if your game would then fail to compile, the design probably needs adjustment. I can give more detail on this if you're interested.

    The above paragraph should certainly be taken in the context of:
    I'm certainly not suggesting you throw out all your existing code if it doesn't follow that principle, just something to learn to do for the future.
     
  18. larswik

    larswik

    Joined:
    Dec 20, 2012
    Posts:
    312
    Thanks. I look at coding this way.... It's like driving from my place to the grocery store. There are probably 100 different routes I could take to get there and some routes will be more efficient the others. As I drive around more and more, I will find better ways to get there over time. Being my first game in Unity and coming from Objective C to C#, it's a lot like I just moved to this town and now discovering better ways to get to the store. I much appreciate the help though. I picked up a learn to program in C book in 93' that came with a floppy disc. I was totally lost learning from a book and gave up. The internet is an amazing resource to help me learn and forums like this to push me in better directions.