Menu
CoddyTech

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.

challenge icon

Wyzwanie

Łatwy

Napisz Fire() w Laser: jeden promień, cztery wyniki.

  1. Wyślij promień za pomocą Physics.Raycast z wieży wzdłuż transform.forward, na odległość range. Jeśli nie trafi, zapisz w logu Missed.
  2. Jeśli hit.collider.TryGetComponent(out IDamageable target), wywołaj TakeDamage(damage) i zapisz w logu "Hit " + hit.collider.name.
  3. W przeciwnym razie, jeśli obiekt ma komponent Rigidbody, wywołaj AddForce(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

Poćwicz samodzielnie: Edytor online Unity