Menu
CoddyTech

Interfaces y TryGetComponent

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 7 de 50.

TryGetComponent solicita un componente y te indica si lo encontró, en una sola llamada. También funciona con interfaces, por lo que suele ser la forma habitual de preguntar al objeto con el que has chocado si puede recibir daño. Esta mina daña a todo lo que tiene a su alrededor que implementa 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 padre ni en sus hijos.

GetComponent informa de forma distinta 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#, así que tanto == null como ?. funcionan con él. TryGetComponent evita esta diferencia en ambos casos y no asigna memoria en el Editor cuando falta el componente.

challenge icon

Desafío

Fácil

La torre láser gira con las flechas izquierda y derecha, y la barra espaciadora llama a Fire() en Laser.cs. Escribe Fire. Lanza un rayo desde la torre en la dirección hacia la que apunta, de range unidades de longitud (el Inspector establece 10), después:

  • Si alcanza algo que tenga un IDamageable, llama a TakeDamage(damage) y registra Hit y el nombre del objeto, como en Hit Robot.
  • Si el objeto no tiene un IDamageable, pero sí un Rigidbody, empújalo con AddForce(transform.forward * push, ForceMode.Impulse) y registra Pushed y su nombre.
  • Cualquier otra cosa registra Blocked by y su nombre, como en Blocked by Pillar. Si el rayo no alcanza nada, registra Missed.

Usa TryGetComponent para ambas búsquedas. IDamageable.cs, Robot.cs y Balloon.cs ya están listos. Pulsa Play y dispara en todas las direcciones; después, pulsa Check.

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
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Arquitectura de juegos en Unity