Menu
CoddyTech

Giao diện và TryGetComponent

Thuộc phần Kiến trúc trò chơi trong Unity trong hành trình Unity của Coddy. Bài học 8 trên 64.

TryGetComponent tìm một thành phần và cho bạn biết liệu nó có tìm thấy thành phần đó hay không, chỉ trong một lần gọi. Phương thức này cũng hoạt động với giao diện, nên đây là cách thường dùng để hỏi đối tượng bạn va phải xem nó có thể bị gây sát thương hay không. Quả mìn này gây sát thương cho mọi thứ xung quanh có thể nhận sát thương:

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 khai báo biến ngay trong lời gọi. TryGetComponent trả về true và gán giá trị cho target khi đối tượng có một thành phần triển khai IDamageable; nếu không thì phương thức trả về false và target là null. Phương thức chỉ kiểm tra chính đối tượng đó, không kiểm tra đối tượng cha hay con.

GetComponent báo thiếu lớp và thiếu giao diện theo cách khác nhau. Trong Editor, GetComponent<Rigidbody>() trên đối tượng không có Rigidbody trả về null giả của Unity: == null cho kết quả true, nhưng ?. không nhận ra giá trị này và lời gọi gây ra MissingComponentException. Giao diện không có null giả: GetComponent<IDamageable>() trả về null thực của C#, nên cả == null và ?. đều hoạt động. TryGetComponent tránh vấn đề này trong cả hai trường hợp, đồng thời không cấp phát gì trong Editor khi thiếu thành phần.

challenge icon

Thử thách

Dễ

Viết Fire() trong Laser: một tia, bốn kết quả.

  1. Bắn Physics.Raycast từ tháp dọc theo transform.forward, với độ dài range. Nếu bắn trượt, ghi lại Missed.
  2. Nếu hit.collider.TryGetComponent(out IDamageable target), gọi TakeDamage(damage) và ghi lại "Hit " + hit.collider.name.
  3. Nếu không, nếu đối tượng có Rigidbody, gọi AddForce(transform.forward * push, ForceMode.Impulse) và ghi lại "Pushed " cùng với tên; nếu không thì ghi lại "Blocked by " cùng với tên.

Nhấn Chơi, xoay và bắn theo mọi hướng. Sau đó nhấn Kiểm tra.

Tự làm thử

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()
    {
        // Phóng một tia dài range đơn vị về phía trước và xử lý đối tượng mà tia chạm phải
    }
}

Tất cả bài học trong Kiến trúc trò chơi trong Unity

Tự luyện tập: Playground Unity