Interfaces et TryGetComponent
Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 7 sur 50.
TryGetComponent recherche un composant et vous indique en un seul appel s’il en a trouvé un. Il fonctionne aussi avec les interfaces, ce qui en fait la méthode habituelle pour demander à l’objet que vous avez touché s’il peut subir des dégâts. Cette mine inflige des dégâts à tout ce qui l’entoure et implémente 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 à l’intérieur de l’appel. TryGetComponent renvoie true et renseigne target lorsque l’objet possède un composant qui implémente IDamageable ; sinon, il renvoie false et target vaut null. Il 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’Editor, GetComponent<Rigidbody>() sur un objet sans Rigidbody renvoie le faux null de Unity : == null est vrai, mais ?. ne le détecte pas et l’appel déclenche MissingComponentException. Une interface n’a pas de faux null : GetComponent<IDamageable>() renvoie un véritable null C#, donc == null et ?. fonctionnent tous deux. TryGetComponent évite cette question dans les deux cas et n’alloue rien dans l’Editor lorsque le composant est absent.
Défi
FacileLa tourelle laser tourne avec les flèches gauche et droite, et la barre d’espace appelle Fire() dans Laser.cs. Écris Fire. Lance un rayon depuis la tourelle dans sa direction avant, sur une longueur de range unités (l’Inspector est réglé sur 10), puis :
- S’il touche un objet qui possède un IDamageable, appelle
TakeDamage(damage)sur cet objet et afficheHitet le nom de l’objet dans le journal, par exempleHit Robot. - Si l’objet n’a pas d’IDamageable mais possède un Rigidbody, pousse-le avec
AddForce(transform.forward * push, ForceMode.Impulse)et affichePushedet son nom dans le journal. - Dans tous les autres cas, affiche
Blocked byet son nom dans le journal, par exempleBlocked by Pillar. Si le rayon ne touche rien, afficheMisseddans le journal.
Utilise TryGetComponent pour les deux recherches. IDamageable.cs, Robot.cs et Balloon.cs sont prêts. Appuie sur Play et tire dans toutes les directions, puis clique sur Check.
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, d’une longueur de range unités, et traite ce qu’il touche
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Architecture de jeu dans Unity
1Des composants, pas des hiérarchies
Des composants simplesUn script de base pour les ennemisDes composants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaire4Données sérialisées
Classes sérialisablesListes dans l’inspecteurÉnumérations dans l’inspecteurRécapitulatif : table de butin7Machines à états
Les états sous forme de classesUne machine à étatsTransitionsLes cerveaux des ennemisRécapitulatif : états d’une porte10Projet : Survivant de l’arène
Le hérosTypes d’ennemis2Interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interaction5ScriptableObjects
Assets de donnéesStatistiques des armesParamètres partagésLes vagues sous forme de donnéesRécapitulatif : base de données d’objets