Menu
CoddyTech

Interfaces et TryGetComponent

Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 8 sur 64.

TryGetComponent demande un composant et t’indique en un seul appel s’il en a trouvé un. Cette méthode fonctionne aussi avec les interfaces, ce qui en fait la façon habituelle de demander à l’objet que tu touches s’il peut subir des dégâts. Cette mine inflige des dégâts à tout ce qui l’entoure et qui est IDamageable :

public class Mine : MonoBehaviour
{
    public float radius = 3f;
    public int damage = 5;

    void OnTriggerEnter(Collider other)
    {
        foreach (Collider c in Physics.OverlapSphere(transform.position, radius))
        {
            if (c.TryGetComponent(out IDamageable target))
            {
                target.TakeDamage(damage);
            }
        }
        Destroy(gameObject);
    }
}

out IDamageable target déclare la variable dans l’appel. TryGetComponent renvoie true et renseigne target lorsque l’objet possède un composant qui implémente IDamageable ; sinon, la méthode renvoie false et target vaut null. Elle examine uniquement cet objet, jamais son parent ni ses enfants.

GetComponent signale différemment l’absence d’une classe et celle d’une interface. Dans l’éditeur, GetComponent<Rigidbody>() appelé sur un objet dépourvu de Rigidbody renvoie le faux null de Unity : == null vaut true, mais ?. ne le détecte pas et l’appel déclenche une MissingComponentException. Une interface n’a pas de faux null : GetComponent<IDamageable>() renvoie un véritable null C#, donc == null et ?. fonctionnent tous les deux. TryGetComponent évite cette question dans les deux cas et n’effectue aucune allocation dans l’éditeur lorsque le composant est manquant.

challenge icon

Défi

Facile

Écris Fire() dans Laser : un rayon, quatre résultats.

  1. Lance Physics.Raycast depuis la tour, dans la direction de transform.forward, sur une distance de range. En cas d’échec, journalise Missed.
  2. Si hit.collider.TryGetComponent(out IDamageable target), appelle TakeDamage(damage) et journalise "Hit " + hit.collider.name.
  3. Sinon, s’il possède un Rigidbody, applique AddForce(transform.forward * push, ForceMode.Impulse) et journalise "Pushed " suivi du nom ; sinon, journalise "Blocked by " suivi du nom.

Appuie sur « Jouer », tourne et tire dans toutes les directions. Ensuite, clique sur « Vérifier ».

Essayez vous-même

using UnityEngine;
using UnityEngine.InputSystem;

public class Laser : MonoBehaviour
{
    public float range = 10f;
    public int damage = 1;
    public float push = 5f;
    public float turnSpeed = 90f;

    private InputAction moveAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
    }

    void Update()
    {
        float turn = moveAction.ReadValue<Vector2>().x;
        transform.Rotate(0f, turn * turnSpeed * Time.deltaTime, 0f);
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            Fire();
        }
    }

    void Fire()
    {
        // Lance un rayon vers l’avant sur une distance de range unités et gère ce qu’il touche
    }
}

Toutes les leçons de Architecture de jeu dans Unity

Entraînez-vous par vous-même : Playground Unity