Schnittstellen und TryGetComponent
Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 8 von 64.
TryGetComponent fragt in einem Aufruf nach einer Komponente und teilt dir mit, ob eine gefunden wurde. Es funktioniert auch mit Schnittstellen und ist daher die übliche Methode, um bei einem getroffenen Objekt abzufragen, ob es verwundet werden kann. Diese Mine fügt allem in ihrer Umgebung Schaden zu, das IDamageable ist:
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 füllt target, 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 Kinder.
GetComponent meldet eine fehlende Klasse und eine fehlende Schnittstelle unterschiedlich. Im Editor gibt GetComponent<Rigidbody>() bei einem Objekt ohne Rigidbody Unitys falsches null zurück: == null ist true, aber ?. erkennt es nicht und der Aufruf löst MissingComponentException aus. Eine Schnittstelle hat kein falsches null: GetComponent<IDamageable>() gibt ein echtes C#-null zurück, sodass == null und ?. beide darauf funktionieren. TryGetComponent vermeidet diese Frage bei beiden, und es allokiert im Editor nichts, wenn die Komponente fehlt.
Aufgabe
EinfachSchreibe Fire() in Laser: ein Strahl, vier mögliche Ergebnisse.
- Führe von der Turmspitze aus entlang
transform.forwardeinenPhysics.Raycastmit der Längerangeaus. Bei einem Fehlschuss protokolliereMissed. - Wenn
hit.collider.TryGetComponent(out IDamageable target)zutrifft, rufeTakeDamage(damage)auf und protokolliere"Hit " + hit.collider.name. - Andernfalls: Wenn das Objekt ein
Rigidbodyhat, wendeAddForce(transform.forward * push, ForceMode.Impulse)an und protokolliere"Pushed "sowie den Namen; andernfalls"Blocked by "sowie den Namen.
Drücke „Spielen“, drehe dich und feuere in jede Richtung. Drücke 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()
{
// Schicke einen Strahl nach vorn, der range Einheiten lang ist, und verarbeite, was er trifft
}
}
Alle Lektionen in Spielarchitektur in Unity
1Komponenten statt Hierarchien
Kleine KomponentenEin Basis-GegnerskriptAbstrakte KomponentenZusammenwirkende KomponentenRückblick: Modulares GeschützRückblick: Zwillingskanone4Serialisierte Daten
Serialisierbare KlassenListen im InspectorEnums im InspectorRückblick: Loot-TabelleRückblick: Beute auswürfeln2Schnittstellen in Unity
IDamageableSchnittstellen und TryGetComponentGetComponentsZusammenfassung: InteraktionstasteZusammenfassung: Nächstes in Reichweite5ScriptableObjects
Daten-AssetsWaffenwerteGemeinsame EinstellungenDen Wind speichernWellen als DatenRückblick: Item-DatenbankRückblick: Im Shop einkaufen8Wiederverwendbarer Code
ErweiterungsmethodenEin generisches SingletonGenerische HilfsmethodenRückblick: FindNearestÜbe selbstständig: Unity-Playground