- Home /
How does gameobject.find() loop through the hierarchy?
My question on this is regarding to the nature of how gameobject.find() loops through the hierarchy.
Does it
loop through in the order that is visually presented in the editor?
Alphabetically/reverse-alpha?
some other method (BST maybe?) ?
I'm asking because I want to find the most efficient way to find a gameobject when i know it exists and is a unique object and will be one only (if not then at most 1 of 10) game object referenced with find() in the scene.
My thought process: If unity does the loop alphabetically, then would having an object named "_restartMarker" then be O1 (constant time) for find("_restartMarker") because it should be the first item checked?
My point also runs on the assumption that Unity will break the loop when it finds the first instance of the object, which, if this isn't true then my question is kaput. In that case, is finding an object by tag then the most efficient way to find a game object? I'm staying away from using a "Public Gameobject Target " assignment in code
I do not know answer to your question, but generally know that Find() is slow and should not be used during runtime if it can be avoided. Is there a reason you need to use Find() ins$$anonymous$$d of FindWithTag()?
Answer by Patxiku · Feb 23, 2017 at 09:25 AM
The documentation says that it iterates all GameObjects.
"It is a general best practice to eliminate all usage of Object.Find and Object.FindObjectOfType in production code. As these APIs require Unity to iterate over all GameObjects and Components in memory, they rapidly become non-performant as the scope of a project grows."
If you are looking for unique GameObjects, you should use the singleton patern as the documentation says:
"An exception to the above rule can be made in accessors for singleton objects. A global manager object often exposes an “instance” property, and often has a FindObjectOfType call in the getter to detect pre-existing instances of the singleton:"
class SomeSingleton {
private SomeSingleton _instance;
public SomeSingleton Instance {
get {
if(_instance == null) {
_instance =
FindObjectOfType<SomeSingleton>();
}
if(_instnace == null) {
_instance = CreateSomeSingleton();
}
return _instance;
}
}
}
Full info here.
While this is true, Unity is inherently bad at writing clear documentation ^^. "iterate over all GameObjects" is only necessary if there is no such object. So it's the worst case scenario. Even then the time it takes is not that huge considering you call that method once at start. Of course using it every frame wouldn't make much sense.
We don't know how they iterate the gameobjects or how exactly they are stored on the native C++ side (where the search will take place). Of course it's in general a good idea to replace a slow procedure with a faster one. However certain solutions (like a singleton) has some other bad characteristics which you also should avoid.
In the end it depends on the actual usecase. However if your project has say 10k objects, searching through them only takes a few µs. Yes, string comparison can be slow but if most of the names differ already in the first character it's like an int-comparison. If you're going to use Find / FindChild / ... you should avoid starting all names with the same long prefix.
The main reason why you should avoid Find is because if you later add more objects and accidentally name another object the same as one that you used to "find", it might break the existing functionality. That's why it's always better to directly link your objects in the inspector.
$$anonymous$$eep in $$anonymous$$d that you can do relative searches as well. So if you have already access to a parent object, searching for child objects is much faster (given there are only a few childs).
Answer by unityBerserker · Feb 23, 2017 at 10:21 PM
Default Hierarchy Sorting is Transform Sorting.
Every gameObject directly in hierarchy is root. All roots are siblings to themseves. (RED ONE).
Every child of root (or more nested gO) is a sibling to other children in that gO(BLUE and GREEN).
In Transform class we have methods like:
SetSiblingIndex(), GetSiblingIndex() and other binded with siblings and roots. That how this sorting work.
GameObject.Find() start searching in hierarchy by sibling index.
Now we searching something like gameObject with name "unity":
Main Camera ... - have no children so we go to FirstRoot
FirstRoot - he have children so now we searching in chldren
Zero Child
FirstChild - we don't find what we want so we back to next root
SecondRoot - we avoided Second Child because it was inactive
Zero Child (in SecondRoot) and as long as we find what we want in hierarchy.
If we find what we want - we stop searching!
Where is a problem?
If we have 1k gameObject and we searching for the last one - the "1000" - first we must check first 999 gameobject to find the "1000" one.
If we put "1000" at beging of hierarchy we find this gameObject instantly.
Thats why when we have bigger hierarchy we spent more time!
Answer by ThisGuyThatsHere · Feb 23, 2017 at 10:31 PM
Why not give it a simple script that will have a static variable of GameObject and you assign your gameObject as the value on Awake()? And ofcourse you can remove that script when you get the refernce, seems faster to me.
Your answer
Follow this Question
Related Questions
Is there a more efficient way to write a "Find" script? 2 Answers
Is there a more efficient way to writ a "Find" script? 0 Answers
Performance gain through recycling Objects? 1 Answer
What's a good draw call count? 2 Answers
Android Best performance 1 Answer