Menu
CoddyTech

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.

challenge icon

Wyzwanie

Łatwy

Wież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 logu Hit oraz nazwę obiektu, na przykład Hit Robot.
  • Jeśli obiekt nie ma IDamageable, ale ma Rigidbody, odepchnij go za pomocą AddForce(transform.forward * push, ForceMode.Impulse) i zapisz w logu Pushed oraz jego nazwę.
  • Każdy inny obiekt zapisuje w logu Blocked by i swoją nazwę, na przykład Blocked by Pillar. Promień, który niczego nie trafi, zapisuje w logu Missed.

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
    }
}
quiz iconSprawdź się

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