Unity GetComponent Presentation

Unity GetComponent, Comment l’utiliser

Sur Unity, les développeurs utilisent fréquemment `GetComponent`. Cette fonction permet de récupérer un composant attaché à votre GameObject. Dans ce guide complet, nous explorons divers aspects de `GetComponent` et fournissons en fin d’article quelques astuces.

Table des matières

Utilisation de base

Unity GetComponent

using UnityEngine;

public class MonoBehaviourComponent : MonoBehaviour
{
    private void Action()
    {
        // Utiliser GetComponent immédiatement, car MonoBehaviour étend Component

        // Méthode de base
        var boxCollider2d = GetComponent<BoxCollider2D>();

        // Avec le type en tant que paramètre
        var box2 = GetComponent(typeof(BoxCollider2D)) as BoxCollider2D;
    }
}

Qu’est-ce qu’un composant ?

Un composant dans Unity est un script C# héritant de `UnityEngine.Component`, attaché à un GameObject pour effectuer diverses tâches telles que le rendu, le gameplay ou la gestion des collisions… Tous les composants ont accès aux fonctions de « recherche » de composants fournies par `UnityEngine.Component`.

Composants Unity dans l'inspecteurInspecteur Unity avec 3 composants

Méthode TryGetComponent

`TryGetComponent` est utilisée dans un scénario où vous n’êtes pas sûr si le composant est attaché à votre GameObject. Cette fonction renvoie `true` si le composant est trouvé.

private void Handle()
{
  if (TryGetComponent<BoxCollider2D>(out BoxCollider2D boxCollider2D))
  {
    boxCollider2D.isTrigger = true;
  }
}

GetComponent pour les interfaces

Vous pouvez également récupérer des composants qui implémentent une interface à l’aide de `GetComponent`. Par exemple, vous pouvez obtenir un composant qui implémente l’interface `IPointerDownHandler`.

using UnityEngine;
using UnityEngine.EventSystems;

public class MonoBehaviourComponent : MonoBehaviour
{
  public GameObject referenceGameObject;

  private void Awake()
  {
    var pointer = referenceGameObject.GetComponent<IPointerDownHandler>();
  }
}

GetComponents

La fonction `GetComponents` vous permet de récupérer tous les composants d’un même type sur un GameObject.

private void Action()
{
  var boxCollider2Ds = GetComponents<BoxCollider2D>();

  foreach (var boxCollider in boxCollider2Ds)
  {
    boxCollider.isTrigger = true;
  }
}

Remarque : Cette fonction renvoie un tableau d’éléments du type spécifié.

Cette fonction peut également être utilisée en passant une liste en tant que paramètre pour éviter de recréer une liste à chaque appel :

private List<BoxCollider2D> _boxColliders = new List<BoxCollider2D>();

private void Update()
{
	GetComponents(_boxColliders);

	foreach(var boxCollider in _boxColliders)
	{
		// effectuer des actions
	}
}

GetComponentInChildren

Unity GetComponentInChildren

`GetComponentInChildren` récupère un composant d’un type spécifique du GameObject lui-même ou d’un GameObject enfant.

private void InChildren()
{
  // Trouver la premiere Image dans lui-même ou ses enfants si leur gameObject est actif
  var image = GetComponentInChildren<Image>();
  image.color = Color.red;

  // Trouver la premiere Image dans lui-même ou ses enfants si leur gameObject est inactif ou actif
  var imageDisabled = GetComponentInChildren<Image>(true);
}

GetComponentsInChildren

Découvrez comment récupérer tous les composants d’un type spécifique du GameObject lui-même et de ses enfants en utilisant `GetComponentsInChildren`.

private void InChildrens()
{
  // Trouver toutes les Images dans lui-même et ses enfants si leur gameObject est actif
  var images = GetComponentsInChildren<Image>();

  foreach (var image in images)
  {
    image.sprite = null;
  }

  // Trouver toutes les Images dans lui-même et ses enfants si leur gameObject est inactif ou actif
  var disabledImages = GetComponentsInChildren<Image>(true);
}

Remarque : Cette fonction peut également être utilisée en passant une liste en tant que paramètre pour éviter de recréer une liste à chaque appel.

GetComponentInParent

Unity GetComponentInParent

`GetComponentInParent` récupère un composant d’un type spécifique du GameObject lui-même ou d’un parent.

private void InParent()
{
  // Trouver la premiere Image dans lui-même ou ses parents si leur gameObject est actif
  var image = GetComponentInParent<Image>();
  image.color = Color.red;

  // Depuis Unity 2020, trouver la premiere Image dans lui-même ou ses parents si leur gameObject est inactif ou actif
  var imageDisabled = GetComponentInParent<Image>(true);
}

GetComponentsInParent

Explorez `GetComponentsInParent` pour récupérer tous les composants d’un type spécifique du GameObject lui-même et de ses parents.

private void InParents()
{
  // Trouver toutes les Images dans lui-même et ses parents si leur gameObject est actif
  var images = GetComponentsInParent<Image>();

  foreach (var image in images)
  {
    image.sprite = null;
  }

  // Trouver toutes les Images dans lui-même et ses parents si leur gameObject est inactif ou actif
  var disabledImages = GetComponentsInParent<Image>(true);
}

Remarque : Pour éviter de recréer une liste à chaque appel, cette fonction peut avoir une liste en tant que paramètre.

Un petit conseil, pour éviter la recherche sur lui-même, vous pouvez appeler la méthode directement sur le parent :

var imagesWithoutSelf = transform.parent.GetComponentsInParent<Image>();

GetComponent par nom (À éviter)

Trouver un composant avec le nom du gameObject n’est pas une bonne approche. La fonction utilisée pour cela est `GameObject.Find`, mais elle n’est pas très efficace. Pour de meilleures performances, vous pouvez utiliser d’autres méthodes telles que les références directes ou le suivi des composants dans un manager.

private void FindByName()
{
  // Évitez cet appel...
  var boxCollider2d = GameObject.Find("NomDeMonGameObject").GetComponent<BoxCollider2D>();
}

Composant par référence

Au lieu d’utiliser `GetComponent`, envisagez de créer une propriété sérialisable pour référencer directement votre composant.

using UnityEngine;

public class MonoBehaviourComponent : MonoBehaviour
{
    public BoxCollider2D boxCollider2D;

    // ou, si vous préférez un champ privé
    [SerializeField]
    private BoxCollider2D _boxCollider2D;
}

Référence de composant avec une liste statique

Utilisez les méthodes `OnEnable` et `OnDisable` pour suivre les composants du même type en les ajoutant et en les supprimant d’une liste statique.

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);
}

Maintenant, nous utilisons l’identifiant (code) au lieu du nom pour appeler le composant, par exemple en utilisant LINQ :

using System.LINQ;

// Exception non gérée dans ce code
var boxCollider2d = MonoBehaviourComponent.ListComponents.Single(x => x.code == "monCode").boxCollider2D;

Référence de composant avec un manager

Créez un manager pour gérer vos composants MonoBehaviour. Le manager peut instancier et détruire des composants, fournissant une approche centralisée pour gérer vos composants.

J’adore utiliser des managers car ils me permettent de développer mon code très facilement. Vous pouvez partir de cette base et ensuite ajouter un système de pool, des événements (events), etc.

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class ComponentManager : MonoBehaviour
{
    // c'est un modèle, peut être un 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);
    }
}

En utilisant notre ancien exemple, nous ferions un appel comme ceci :

var boxCollider2d = ComponentManager.Instance.GetComponentByCode("monCode").boxCollider2D;

Bonnes pratiques de GetComponent (Éviter les NullReferenceException)

Il est recommandé dans un Monobehaviour de définir vos appels `GetComponent` dans la méthode `Awake` puis de les utiliser pendant ou après la méthode `Start` pour éviter les `NullReferenceException`. Dans ce schéma `Awake` est utilisé uniquement pour définir des composants ou des Singletons, et `Start` est utilisé pour la configuration.

[SerializeField]
private BoxCollider2D _boxCollider2D;

private void Awake()
{
  _boxCollider2D = GetComponent<BoxCollider2D>();
}

private void Start()
{
  _boxCollider2D.isTrigger = true;
}

Éviter GetComponent dans Update

Mettez en cache vos appels `GetComponent` dans un champ ou évitez de les appeler à chaque frame. N’oubliez pas que, par défaut, aucun cache n’est appliqué à ces fonctions. Si vous appelez, par exemple, `GetComponentInParent` dans un `Update`, cela recherchera tous les parents à chaque frame, ce qui peut potentiellement affecter vos performances.

[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)
  {
    // Effectuer des actions avec le contact
  }
}

Conclusion

J’espère que ce tutoriel vous a fourni des informations précieuses sur les composants dans Unity. Que vous soyez débutant ou développeur expérimenté, maîtriser l’utilisation de `GetComponent` et de ces méthodes associées est crucial pour un développement efficace.

Merci de l’avoir lu.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *