🤔 Unity, huh, how?

🤔

GetComponent methods

GetComponent, TryGetComponent, GetComponentInChildren, and other similar methods are perfect for dynamic runtime references like those gathered in a physics message or query.

It's preferable to use serialized references where possible.

Use with interfaces

The GetComponent family of functions can return components that implement interfaces, making them powerful tools to work with composition.

Example

using UnityEngine;

/// <summary>
/// Damages components marked with <see cref="IDamageable"/> that enters the attached trigger.
/// </summary>
public class DamageTrigger : MonoBehaviour
{
	[SerializeField] private int _damage = 100;

	void OnTriggerEnter(Collider collider)
	{
		if (!collider.TryGetComponent(out IDamageable damageable))
		{
			// Exit early, the collider's object doesn't have an IDamageable component.
			return;
		}

		// Call our Damage method.
		damageable.Damage(_damage);
	}
}

/// <summary>
/// Marks a component as capable of receiving damage.
/// </summary>
public interface IDamageable
{
	void Damage(int amount);
}

/// <summary>
/// Our player can receive damage from <see cref="IDamageable"/> sources.
/// </summary>
public class Player : MonoBehaviour, IDamagable
{
	public void Damage(int amount)
	{
		// ...
	}
}

Notes

Garbage collection

GetComponent

Due to Unity null, GetComponent will always allocate in the editor, whereas using TryGetComponent will not.

Collection pools

Unity provides various collection pool classes (introduced in 2021.1) that can be used in combination with the multi-object GetComponent functions. Do note that pooled collections can last the lifetime of your application, and care must be taken when allocating them.

using (ListPool<IDamageable>.Get(out var damageables))
{
	collider.GetComponentsInChildren(damageables);
	foreach (IDamageable damageable in damageables)
		damageable.Damage(_damage);
}

See ListPool.