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.
Aufgabe
EinfachDer 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 protokolliereHitund den Namen des Objekts, zum BeispielHit Robot. - Wenn das Objekt kein IDamageable, aber ein Rigidbody hat, stoße es mit
AddForce(transform.forward * push, ForceMode.Impulse)weg und protokollierePushedund seinen Namen. - Bei allem anderen werden
Blocked byund der Name protokolliert, zum BeispielBlocked by Pillar. Ein Strahl, der nichts trifft, protokolliertMissed.
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
}
}
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
1Komponenten statt Hierarchien
Kleine KomponentenEin Basisskript für GegnerAbstrakte KomponentenKomponenten im ZusammenspielRückblick: Modularer Geschützturm4Serialisierte Daten
Serialisierbare KlassenListen im InspectorEnums im InspectorRückblick: Loot-Tabelle7Zustandsautomaten
Zustände als KlassenEin ZustandsautomatÜbergängeGegner-KIWiederholung: Türzustände10Projekt: Arena-Überlebenskampf
Der HeldGegnertypen2Interfaces in Unity
IDamageableInterfaces und TryGetComponentGetComponentsRückblick: Interaktionstaste5ScriptableObjects
Daten-AssetsWaffenwerteGemeinsame EinstellungenWellen als DatenRückblick: Item-Datenbank8Wiederverwendbarer Code
ErweiterungsmethodenEin generisches SingletonGenerische HilfsmethodenRückblick: FindNearest