Dependencies in videogames are inevitable. You’ll have different scripts that need to access a certain component within the same GameObject or in another one at one point. Some examples of dependencies would be:
- Needing some components such as Rigidbodies, so we can access their methods such as MovePosition() or MoveRotation().
- A GameManager, that needs a reference to the player so it can save the player’s progress and properly display it.
- An enemy, which requires a reference to a certain target to follow.
In the end, the process of linking every component together to make our defined entities work as they should is no different than building a robot piece by piece.
Today, I will cover the basics of obtaining references to components in any GameObject in Unity. There are more ways to obtain a reference, but that’s a topic for another day.
Two things to have in mind
Using [SerializeField] for private variables
There’s a way to avoid getting components through code, and that’s by serializing variables. This will expose the variables to the editor, making it easy to drag and drop the components references.
Use this only for local references. If you do this for external GameObjects, you’ll couple too much your game with dependencies and will lead to errors.
Cache your variables
Getting components at run-time is a expensive operation, and you must avoid using the following methods in the Update() method (you’ll completely botch your game’s performance).
If you are dealing with local components that you need to access, and that they won’t be destroyed, cache it in the Awake() or Start().
This is the most basic method of obtaining a reference to a Component. It will try to look for a specified component in the GameObject (it won’t look for parent or child components), and returns the first one it finds. Or if it doesn’t find anything, it will return null.
This is useful if you have only one specific component in a GameObject. For example, if I want to get the Ship’s collider by code and then change the collider to a Trigger, I would do this:
GetComponentInParent | GetComponentInChildren
The same as GetComponent, but it will recursively look for the first component it finds in their parents | children.
For example, I want to access an Animator component that is not located on the local Ship GameObject. It is the only Animator within the children, and I want to cache it through code.
To do that, it’s as simple as doing the following:
GetComponents | InParent | InChildren
These methods will get every component within the local GameObject | the parent | children GameObjects. These methods are rarely used, only for specific cases such as getting all colliders within a group of GameObjects (a GameObject with children) and disabling them.
It will return an array of those components (or null if it doesn’t find anything), so you’ll need to declare a variable as an array.
This is a more performant way to get a local component from your GameObject. This is very useful for behaviours that need to check if a component exists, and if it does, hand you the reference at the same time.
Unfortunately, there are no similar methods to look for a parent or children component, or multiple components.
My laser’s functionality uses this method to check if it hit an Enemy and deal damage if the reference is not null.
FindObjectOfType | FindObjectsOfType
When looking for components in parents or children is not enough, you can do a global search using these methods. They are commonly used to get references to centric GameObjects (such as the player’s avatar, to get the status and other stuff).
In my game, I have a GameManager that tracks the Player’s ship status. To get the reference, I use this method:
This was an extensive article on how to find references and fill your dependencies in your game. You have all the tools at your disposal, now use them carefully because your game optimization depends on how you implement them.
Remember to not overload your Robot by checking for components in the Update() method!