0
\$\begingroup\$

I been following the playlist in brackeys for unity for beginners and it gets a little fast and complicated at the end and just curious about if a script makes a reference like:

FindObjectOfType<GameManager>().EndGame();

With GameManager being a empty and EndGame being a function to another script.

It runs it but does it connect to the script through the GameManager object since it's connected to the script?

I just want to know how it's getting to the script function and that is the only mention of GameManager in the whole script.

Inspector of GameManager EndGame Function in script FindObectOfType in script Player Inspector & Hierarchy

\$\endgroup\$
1
\$\begingroup\$

Why is this happening?

Unity's "FindObjectOfType()" function looks through the entire hierarchy (not just the object the script is on) for the first active instance of a game object with the type specified. More info can be found in the official documentation.

If you look in your hierarchy under the "LevelOne" scene you can see that you have your GameManager object active in the list. So when your player script calls this "FindObjectOfType()" function Unity is returning the first item in its hierarchy which matches your request. Then you call "EndGame()" on this returned object.

What does FindObjectOfType return?

In response to your question on @LinkWindcrafter's answer: An "Object" and a "GameObject" are two separate things. Each item in your hierarchy is an individual GameObject. Each GameObject has a list of components which you can view and edit in the inspector after selecting a GameObject. Components and GameObjects both derive from Unity's base class Object.

Object > GameObject

and

Object > Component > Behavior > MonoBehavior > Your GameManager

In short:

FindObjectOfType<GameManager>()

returns an Object cast as a GameManager type, and then you call it's "EndGame()" function on it. The specific object being returned is the first instance of your script that Unity can find in your scene hierarchy.

Using the Component property "gameobject" you can retrieve the GameObject it is attached to if you wish:

GameObject go = self.gameobject;

Potential Problems

As the documentation mentions this function is very slow. It loops through every active game object in your entire scene and does a check to see if it's what your looking for. The bigger your scenes get the longer this function will take. I typically see it used in initialization where you can afford to do inefficient calls rather than update where you want to trim down your processing times.

The documentation also mentions that it returns the first active object matched. So if the object is turned off, or there is a second one which matches your request you may get the wrong object (or null if there isn't one) which could either crash your game, or cause unexpected results.

This next problem is more nit picky than actually discussing functionality. As you've already encountered this function isn't the most readable. It's a borderline global call and it makes it difficult to know not only which object is being used, but also which object was intended to be used.

Solutions

I can see in the pictures you've posted that your familiar with setting up scripting variables that you can alter from within the editor. If you add either a public, or (better) a [SerializeField] GameManager variable to the script your calling it from you can assign it in the editor by dragging and dropping the instance you want to use. This will let whoever is looking at your script know exactly which object you want to call "EndGame()" on, and it will avoid the issue of calling the slow "FindObjectOfType()" function.

\$\endgroup\$
  • \$\begingroup\$ Is it possible to utilize an IoC container within Unity to help with this? Or even MEF? \$\endgroup\$ – Slagmoth Mar 22 '18 at 20:24
  • \$\begingroup\$ @Slagmoth sorry for the delayed reply. It's really up to you how you set up your architecture but I'm generally in favor of Dependency Injection where possible even if Unity makes it difficult sometimes. It looks like the GameManager in this question is a Single Instance, so that's something to consider as well. \$\endgroup\$ – DrewAtWork Mar 26 '18 at 14:30
-1
\$\begingroup\$

What that line does is that it fetches for a UnityEngine's Object on the scene with the type defined on the angle brackets, it returns that script, or null if there wasn't one.

The way script references work on Unity is that the script fetched needs to be attached to a GameObject, FindObjectOfType searches if GameObjects on the scene have that script attached.

That is the reason it makes that function call once, otherwise it would have stored it on a variable of that type. Like this:

public class Example : MonoBehaviour
{
    private GameManager manager;
    public bool condition;

    void Start()
    {
        manager = FindObjectOfType<GameManager>() as GameManager;
    }

    Update()
    {
        if(condition) manager.EndGame();
    }
}

See the method's documentation for reference.

\$\endgroup\$
  • \$\begingroup\$ sorry I'm still new to unity but I think I understand a little. Is the basics of what your saying that it searches for the object GameManager but the function call at the end makes it search for the script on the object with that function? Or does the function call at the end make it search only for the script? \$\endgroup\$ – Spiritual Learning Mar 21 '18 at 21:40
  • \$\begingroup\$ Distinctions should be made when talking about scripts and instances of object. This adds noise that could confuse a new user. \$\endgroup\$ – Vaillancourt Mar 21 '18 at 22:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.