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.
Défi
FacileÉcris Fire() dans Laser : un rayon, quatre résultats.
- Lance
Physics.Raycastdepuis la tour, dans la direction detransform.forward, sur une distance derange. En cas d’échec, journaliseMissed. - Si
hit.collider.TryGetComponent(out IDamageable target), appelleTakeDamage(damage)et journalise"Hit " + hit.collider.name. - Sinon, s’il possède un
Rigidbody, appliqueAddForce(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
1Des composants, pas des hiérarchies
De petits composantsUn script de base pour les ennemisComposants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaireRécapitulatif : canon double4Données sérialisées
Classes sérialisablesListes dans l’InspecteurÉnumérations dans l’InspecteurRécapitulatif : table de butinRécapitulatif : tirer le butin2Les interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interactionLe plus proche à portée5ScriptableObjects
Ressources de donnéesStatistiques des armesParamètres partagésSauver le ventLes vagues comme donnéesRécapitulatif : base de données des objetsRécapitulatif : acheter dans la boutique3Événements
Les événements C# dans UnityS’abonner dans OnEnableChamps UnityEventLes événements pilotent l’interfaceRécapitulatif : fenêtre de succèsRécapitulatif : minuteur de la fenêtreEntraînez-vous par vous-même : Playground Unity