Interfejsy i TryGetComponent
Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 8 z 64.
TryGetComponent wyszukuje komponent i w jednym wywołaniu informuje, czy go znalazł. Działa również z interfejsami, dlatego zwykle używa się go, aby sprawdzić, czy obiekt, w który trafisz, może otrzymywać obrażenia. Ta mina zadaje obrażenia wszystkim obiektom w swoim zasięgu, 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 wywołanie GetComponent<Rigidbody>() na obiekcie bez Rigidbody zwraca fałszywe null Unity: == null ma wartość true, ale ?. tego nie wykrywa, a wywołanie powoduje wyjątek MissingComponentException. Interfejs nie ma fałszywego null: GetComponent<IDamageable>() zwraca prawdziwe C# null, więc działają zarówno == null, jak i ?.. TryGetComponent pozwala uniknąć tego problemu w obu przypadkach i nie przydziela pamięci w Edytorze, gdy brakuje komponentu.
Wyzwanie
ŁatwyNapisz Fire() w Laser: jeden promień, cztery wyniki.
- Wyślij promień za pomocą
Physics.Raycastz wieży wzdłużtransform.forward, na odległośćrange. Jeśli nie trafi, zapisz w loguMissed. - Jeśli
hit.collider.TryGetComponent(out IDamageable target), wywołajTakeDamage(damage)i zapisz w logu"Hit " + hit.collider.name. - W przeciwnym razie, jeśli obiekt ma komponent
Rigidbody, wywołajAddForce(transform.forward * push, ForceMode.Impulse)i zapisz w logu"Pushed "oraz nazwę; w przeciwnym razie zapisz w logu"Blocked by "oraz nazwę.
Naciśnij „Graj”, obracaj się i strzelaj we wszystkich kierunkach. Następnie kliknij „Sprawdź”.
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
}
}
Wszystkie lekcje w sekcji Architektura gier w Unity
1Komponenty, nie hierarchie
Małe komponentyBazowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPowtórka: modułowa wieżyczkaPowtórka: podwójne działo4Dane serializowane
Klasy serializowalneListy w InspectorzeEnumy w InspectorzePodsumowanie: tabela łupówPodsumowanie: losowanie łupów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPowtórka: klawisz interakcjiPowtórka: najbliższy w zasięgu5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaOcal wiatrFale jako danePowtórka: Baza przedmiotówPowtórka: Kupowanie w sklepie8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearestPoćwicz samodzielnie: Edytor online Unity