Menu
CoddyTech

Interfaces und TryGetComponent

Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 7 von 50.

TryGetComponent sucht in einem einzigen Aufruf nach einer Komponente und teilt dir mit, ob es eine gefunden hat. Es funktioniert auch mit Schnittstellen und ist daher die übliche Methode, um das getroffene Objekt zu fragen, ob es Schaden erleiden kann. Diese Mine fügt allem in ihrer Umgebung Schaden zu, das IDamageable implementiert:

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 deklariert die Variable innerhalb des Aufrufs. TryGetComponent gibt true zurück und weist target einen Wert zu, wenn das Objekt eine Komponente hat, die IDamageable implementiert; andernfalls gibt es false zurück und target ist null. Es prüft nur dieses eine Objekt, niemals dessen übergeordnetes Objekt oder dessen untergeordnete Objekte.

GetComponent meldet eine fehlende Klasse und eine fehlende Schnittstelle unterschiedlich. Im Editor gibt GetComponent<Rigidbody>() für ein Objekt ohne Rigidbody Unitys falsches null zurück: == null ist true, aber ?. erkennt es nicht und der Aufruf löst eine MissingComponentException aus. Bei einer Schnittstelle gibt es kein falsches null: GetComponent<IDamageable>() gibt ein echtes C#-null zurück, sodass == null und ?. beide funktionieren. TryGetComponent umgeht diese Frage in beiden Fällen und alloziert im Editor nichts, wenn die Komponente fehlt.

challenge icon

Aufgabe

Einfach

Der Laserturm dreht sich mit den Pfeiltasten nach links und rechts, und die Leertaste ruft Fire() in Laser.cs auf. Schreibe Fire. Wirf einen Strahl vom Turm in dessen Vorwärtsrichtung, der range Einheiten lang ist (im Inspector ist 10 eingestellt), dann:

  • Wenn er etwas trifft, das ein IDamageable hat, rufe darauf TakeDamage(damage) auf und protokolliere Hit und den Namen des Objekts, zum Beispiel Hit Robot.
  • Wenn das Objekt kein IDamageable, aber ein Rigidbody hat, stoße es mit AddForce(transform.forward * push, ForceMode.Impulse) weg und protokolliere Pushed und seinen Namen.
  • Bei allem anderen werden Blocked by und der Name protokolliert, zum Beispiel Blocked by Pillar. Ein Strahl, der nichts trifft, protokolliert Missed.

Verwende TryGetComponent für beide Abfragen. IDamageable.cs, Robot.cs und Balloon.cs sind bereit. Drücke Spielen und feuere in jede Richtung, dann Prüfen.

Probier es selbst

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()
    {
        // Wirf einen Strahl nach vorne, der range Einheiten lang ist, und verarbeite, was er trifft
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Spielarchitektur in Unity