Interfejsy i TryGetComponent
Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 7 z 50.
TryGetComponent szuka komponentu i informuje Cię, czy go znalazła, w jednym wywołaniu. Działa też z interfejsami, dzięki czemu jest zwykle stosowanym sposobem, by sprawdzić, czy obiekt, w który trafisz, może otrzymywać obrażenia. Ta mina zadaje obrażenia wszystkim obiektom wokół niej, które implementują 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 deklaruje zmienną wewnątrz wywołania. TryGetComponent zwraca true i przypisuje wartość do target, gdy obiekt ma komponent implementujący IDamageable; w przeciwnym razie zwraca false, a target ma wartość null. Sprawdza tylko ten jeden obiekt, nigdy jego rodzica ani dzieci.
GetComponent różnie sygnalizuje brak klasy i brak interfejsu. W edytorze Unity wywołanie GetComponent<Rigidbody>() na obiekcie bez Rigidbody zwraca fałszywy null Unity: == null ma wartość true, ale ?. go nie wykrywa, a wywołanie powoduje wyjątek MissingComponentException. Interfejs nie ma fałszywego nulla: GetComponent<IDamageable>() zwraca prawdziwy null języka C#, więc działają na nim zarówno == null, jak i ?.. TryGetComponent pozwala uniknąć tego problemu w obu przypadkach i nie alokuje pamięci w edytorze, gdy brakuje komponentu.
Wyzwanie
ŁatwyWieża laserowa obraca się za pomocą strzałek w lewo i w prawo, a spacja wywołuje Fire() w Laser.cs. Napisz funkcję Fire. Rzuć promień z wieży w kierunku, w którym jest skierowana, na odległość range jednostek (Inspector ustawia wartość 10), a następnie:
- Jeśli trafi w coś, co ma IDamageable, wywołaj na tym
TakeDamage(damage)i zapisz w loguHitoraz nazwę obiektu, na przykładHit Robot. - Jeśli obiekt nie ma IDamageable, ale ma Rigidbody, odepchnij go za pomocą
AddForce(transform.forward * push, ForceMode.Impulse)i zapisz w loguPushedoraz jego nazwę. - Każdy inny obiekt zapisuje w logu
Blocked byi swoją nazwę, na przykładBlocked by Pillar. Promień, który niczego nie trafi, zapisuje w loguMissed.
Użyj TryGetComponent w obu wyszukiwaniach. Pliki IDamageable.cs, Robot.cs i Balloon.cs są gotowe. Naciśnij Play i strzelaj w każdym kierunku, a następnie kliknij Check.
Spróbuj swoich sił
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()
{
// Wyślij promień do przodu na odległość range jednostek i obsłuż to, w co trafi
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Architektura gier w Unity
1Komponenty, nie hierarchie
Małe komponentyPodstawowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPodsumowanie: modułowa wieżyczka4Dane serializowane
Klasy serializowalneListy w InspectorzeWyliczenia w InspectorzePodsumowanie: tabela łupów10Projekt: Arena przetrwania
BohaterTypy wrogów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPodsumowanie: klawisz interakcji5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaFale jako danePowtórka: baza danych przedmiotów8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearest