What's the difference between GetComponent and FindObjectsOfType?

I’m confused about the difference between FindObjectsOfType and GetComponent

I’m creating a UI that has Toggles. I add them to the scene via Add > UI > Toggle. From script I access all my Toggles using FindGameObjects:

allToggles = GameObject.FindObjectsOfType(typeof(Toggle)) as Toggle[];
foreach (Toggle go in allToggles) {
   Debug.Log("checked: " + go.isOn);
}

This works, but I found GameObjects, not Components, right?

So why does it say in the documentation, and many other code examples, that you have to use GetComponent(); to find the component on the gameobject? This code is from the Unity documentation:

public class Example : MonoBehaviour
{
    Toggle m_Toggle;
    void Start()
    {
        //Fetch the Toggle GameObject
        m_Toggle = GetComponent<Toggle>();
    }
}

Does a Toggle GameObject HAVE a Toggle Component? Or IS it a component ???

Nope, FindObjectOfType can directly find components. It’s a really slow and inefficient function, but it can directly find components.

That example simply shows how to get a component on the same GameObject as that script. It doesn’t say that you have to do anything.

GameObjects are just bags of components. They never are components.

FindObjectOfType is like “Is there any object of this type in the whole game right now?”. Then it searches the whole world to answer that question. GetComponent just searches a single GameObject.

Note the difference between “object” and “GameObject”.

3 Likes

This has confused me too, especially with the UI gameObjects/components. If you choose GameObject–UI–Text, that shows up as a gameObject in the hierarchy. All good. However, that gameObject has a Text component on it. So, yeah…

1 Like

Exactly! And when you have a public variable for a component, you drag a GameObject on the field, not a component! But even then you can manipulate it directly. For example:

public Text myField;

void Start(){
   myField.text = "Hello";
}

I didn’t have to look for the text component using GetComponent();

Yesn’t. If you drag a GameObject into a field that serializes a reference to a component, Unity looks up all the components on that GameObject and chooses the one that matches the type of the component for that field. Try dragging a GameObject into such a field that has not the required component. Unity should either refuse to let you drag it into that field or add the component to the GameObject.

As for the difference of GetComponent and FindObjectsOfType, think about a multi-party house with all parties sharing the same furniture, inlcuding a coffee machine. Every party has their own coffee machine as part of their furniture. Your furniture is your GameObject. If you call GetComponent on your furniture with T representing your coffee machine, you get exactly one coffee machine, your coffee machine from your furniture. If you call FindObjectsOfType, that’s like knocking on the door of all of the other parties in your house and asking to see and grab their coffee machine.

My opinion is if you find yourself needing FindObjectsOfType then you’re facing a problem of bad design on your end. As already mentioned it is slow, but additionally it can lead to later hard to find bugs.

For example, say you’re using it as in the OP to find all Toggles and turn them all on. It works fine. Then 6 months later someone else working on your project adds a new Toggle, and wants it to start in the off state. But they find it keeps turning on for seemingly no reason, even though they just added it, it starts in the off state, and nothing else in the project references it. Might take them half a day to find the source of the problem with your FindObjectsOfType call.

It would be better to just turn on the specific Toggles you want to turn on, instead of affecting all Toggles globally, to avoid issues later on. Direct references to the Toggles would be better, or references to the GameObjects and then using GetComponent, instead of using FindObjectsOfType. My opinion at least.

1 Like