Menu
CoddyTech

Interfaces y TryGetComponent

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 8 de 64.

TryGetComponent solicita un componente e indica si lo encontró, todo en una sola llamada. También funciona con interfaces, por lo que es la forma habitual de preguntar a lo que sea que golpees si puede recibir daño. Esta mina daña todo lo que hay a su alrededor que sea 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 declara la variable dentro de la llamada. TryGetComponent devuelve true y asigna un valor a target cuando el objeto tiene un componente que implementa IDamageable; de lo contrario, devuelve false y target es null. Solo busca en ese objeto, nunca en su objeto padre ni en sus objetos secundarios.

GetComponent informa de manera diferente si falta una clase o una interfaz. En el Editor, GetComponent<Rigidbody>() en un objeto sin Rigidbody devuelve el null falso de Unity: == null es true, pero ?. no lo detecta y la llamada lanza MissingComponentException. Una interfaz no tiene un null falso: GetComponent<IDamageable>() devuelve un null real de C#, por lo que == null y ?. funcionan con él. TryGetComponent evita esta cuestión en ambos casos y no asigna memoria en el Editor cuando falta el componente.

challenge icon

Desafío

Fácil

Escribe Fire() en Laser: un rayo, cuatro resultados.

  1. Lanza Physics.Raycast desde la torre siguiendo transform.forward, con una longitud de range. Si no acierta, registra Missed.
  2. Si hit.collider.TryGetComponent(out IDamageable target), llama a TakeDamage(damage) y registra "Hit " + hit.collider.name.
  3. Si no, si tiene un Rigidbody, aplica AddForce(transform.forward * push, ForceMode.Impulse) y registra "Pushed " seguido del nombre; si no, "Blocked by " seguido del nombre.

Pulsa «Jugar», gira y dispara en todas direcciones. Después, pulsa «Comprobar».

Pruébalo tú mismo

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()
    {
        // Lanza un rayo hacia adelante de range unidades de longitud y gestiona lo que alcance
    }
}

Todas las lecciones de Arquitectura de juegos en Unity

Practica por tu cuenta: Playground de Unity