Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
We use cookies to ensure that we provide you with the best possible experience on our site.
Your essential source on Unity and web development
Your essential source on Unity and web development
In Unity, developers often find themselves relying heavily on `GetComponent`.
This function allows you to retrieve a component attached to your GameObject. In this comprehensive guide, we explore various aspects of `GetComponent` and provide valuable tips and tricks.
Table of Contents
using UnityEngine;
public class MonoBehaviourComponent : MonoBehaviour
{
private void Action()
{
// Using GetComponent right away, as MonoBehaviour extends Component
// Base Method
var boxCollider2d = GetComponent<BoxCollider2D>();
// With type as a parameter
var box2 = GetComponent(typeof(BoxCollider2D)) as BoxCollider2D;
}
}
A component in Unity is a C# script inheriting from `UnityEngine.Component`, attached to a GameObject to perform various tasks such as rendering, gameplay, or collision handling… All components have access to the component “search” functions provided by `UnityEngine.Component`.
Unity Inspector with 3 components
`TryGetComponent` is used in a scenario where you are unsure if the component is attached to your GameObject. This function returns `true` if the component is found.
private void Handle()
{
if (TryGetComponent<BoxCollider2D>(out BoxCollider2D boxCollider2D))
{
boxCollider2D.isTrigger = true;
}
}
You can also retrieve components that implement an interface using `GetComponent`. For example, you can get a component that implements the `IPointerDownHandler` interface.
using UnityEngine;
using UnityEngine.EventSystems;
public class MonoBehaviourComponent : MonoBehaviour
{
public GameObject referenceGameObject;
private void Awake()
{
var pointer = referenceGameObject.GetComponent<IPointerDownHandler>();
}
}
The `GetComponents` function allows you to retrieve all components of a same type to a GameObject.
private void Action()
{
var boxCollider2Ds = GetComponents<BoxCollider2D>();
foreach (var boxCollider in boxCollider2Ds)
{
boxCollider.isTrigger = true;
}
}
Note: This function returns an array of elements of the specified type.
This function can also be used by passing a list as a parameter to avoid having to recreate a list on each call:
private List<BoxCollider2D> _boxColliders = new List<BoxCollider2D>();
private void Update()
{
GetComponents(_boxColliders);
foreach(var boxCollider in _boxColliders)
{
// do some actions
}
}
`GetComponentInChildren` retrieves a component of a specific type from the GameObject itself or from a child GameObject.
private void InChildren()
{
// Find first Image in itself or its children (work only if gameObject is active)
var image = GetComponentInChildren<Image>();
image.color = Color.red;
// Find first Image in itself or its children
var imageDisabled = GetComponentInChildren<Image>(true);
}
Discover how to retrieve all components of a specific type from the GameObject itself and its childrens using `GetComponentsInChildren`.
private void InChildrens()
{
// Find all Images in itself & its children (work only if gameObject is active)
var images = GetComponentsInChildren<Image>();
foreach (var image in images)
{
image.sprite = null;
}
// Find all Images in itself & its children
var disabledImages = GetComponentsInChildren<Image>(true);
}
Note: This function can also be used by passing a list as a parameter to avoid having to recreate a list on each call.
`GetComponentInParent` retrieve a component of a specific type from the GameObject itself or from a parent.
private void InParent()
{
// Find the first Image in itself or its parents (work only if gameObject is active)
var image = GetComponentInParent<Image>();
image.color = Color.red;
// Since Unity 2020, find the first Image in itself or its parents
var imageDisabled = GetComponentInParent<Image>(true);
}
Explore `GetComponentsInParent` to retrieve all components of a specific type in the GameObject itself and its parents.
private void InParents()
{
// Find all Images in itself & its parents (work only if gameObject is active)
var images = GetComponentsInParent<Image>();
foreach (var image in images)
{
image.sprite = null;
}
// Find all Images in itself & its parents
var disabledImages = GetComponentsInParent<Image>(true);
}
Note: To avoid recreating a list on each call, this function can have a list as parameter.
A little tip, to avoid searching on itself, you can call the method directly on the parent:
var imagesWithoutSelf = transform.parent.GetComponentsInParent<Image>();
Finding a component with the name of the gameObject is not a good approach. The function used to do this is `GameObject.Find`, but it’s not very efficient. For better performance you can use other methods such as direct references or tracking components in a manager.
private void FindByName()
{
// Avoid this call...
var boxCollider2d = GameObject.Find("MyGameObjectName").GetComponent<BoxCollider2D>();
}
Instead of using `GetComponent`, consider creating a serializable property to reference your component directly.
using UnityEngine;
public class MonoBehaviourComponent : MonoBehaviour
{
public BoxCollider2D boxCollider2D;
// or, if you prefer a private field
[SerializeField]
private BoxCollider2D _boxCollider2D;
}
Utilize the `OnEnable` and `OnDisable` methods to track components of the same type by adding and removing them from a static list.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MonoBehaviourComponent : MonoBehaviour
{
public BoxCollider2D boxCollider2D;
public string code;
public static List<MonoBehaviourComponent> ListComponents { get; private set; } = new List<MonoBehaviourComponent>();
private void OnEnable() => ListComponents.Add(this);
private void OnDisable() => ListComponents.Remove(this);
}
Now we use the identifier (code) instead of the name to call the component, e.g. using LINQ:
using System.LINQ;
// Expection not handle in this code
var boxCollider2d = MonoBehaviourComponent.ListComponents.Single(x => x.code == "myCode").boxCollider2D;
Create a manager to handle your MonoBehaviour components. The manager can instantiate and destroy components, providing a centralized way to manage your components.
I love using managers because they allow me to develop my code very easily. You can start from this base and then add a pool system, events …
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class ComponentManager : MonoBehaviour
{
// it's a model, can be a prefab
public MonoBehaviourComponent monoBehaviourComponent;
public List<MonoBehaviourComponent> components = new List<MonoBehaviourComponent>();
public static ComponentManager Instance { get; private set; }
private void Awake()
{
Instance = this;
}
public void InvokeComponent(string code)
{
var instance = Instantiate(monoBehaviourComponent);
instance.code = code;
components.Add(instance);
}
public void DestroyComponent(MonoBehaviourComponent component)
{
if (components.Contains(component))
{
components.Remove(component);
}
Destroy(component.gameObject);
}
public MonoBehaviourComponent GetComponentByCode(string code)
{
return components.SingleOrDefault(x => x.code == code);
}
}
Using our old example, we would make a call like this:
var boxCollider2d = ComponentManager.Instance.GetComponentByCode("myCode").boxCollider2D;
It is recommended in a Monobehaviour to define your `GetComponent` calls in the `Awake` method and then use them during or after the `Start` method to avoid `NullReferenceException`. This pattern ensures that `Awake` is only used for defining components or Singletons, and `Start` is used for configuration.
[SerializeField]
private BoxCollider2D _boxCollider2D;
private void Awake()
{
_boxCollider2D = GetComponent<BoxCollider2D>();
}
private void Start()
{
_boxCollider2D.isTrigger = true;
}
Cache your `GetComponent` calls in a field or avoid calling them every frame. Remember that, by default, no caching is applied to these functions. If you call, for example, `GetComponentInParent` in an `Update`, it will search through all parents every frame, potentially harming performance.
[SerializeField]
private BoxCollider2D _boxCollider2D;
private List<ContactPoint2D> _contactPoints = new List<ContactPoint2D>();
private void Awake()
{
_boxCollider2D = GetComponent<BoxCollider2D>();
}
private void FixedUpdate()
{
if (_boxCollider2D.GetContacts(_contactPoints) > 0)
{
// Perform actions with contact
}
}
I hope this tutorial has provided valuable insights into working with components in Unity. Whether you are a beginner or an experienced developer, mastering the usage of `GetComponent` and related methods is crucial for efficient Unity development.
Thank you for reading.