Menu
CoddyTech

Null trong Unity

Thuộc phần Những kiến thức cơ bản về lập trình trong Unity trong hành trình Unity của Coddy. Bài học 60 trên 85.

Một đối tượng Unity có hai phần: đối tượng C# mà script của bạn giữ và đối tượng của engine nằm phía sau. Destroy(obj) xóa phần của engine vào cuối khung hình, nhưng biến của bạn vẫn trỏ đến phần C#, nên theo cách hiểu thông thường của C#, nó không phải là null. Unity ghi đè toán tử == để xử lý trường hợp này: sau khi đối tượng bị hủy, obj == null là true, và phép kiểm tra ngắn !obj cũng vậy. Đây là null giả của Unity.

?., ?? và is null không dùng == đó. Chúng kiểm tra tham chiếu C#, vốn vẫn tồn tại, nên vẫn cho phép lời gọi tiếp tục. Việc truy cập đối tượng đã bị hủy sẽ gây ra MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Nhãn này hiển thị tên người dẫn đầu cuộc đua, người có thể bị loại (bị hủy):

[SerializeField] private Transform leader;

void Update()
{
    // Gây ngoại lệ khi leader bị hủy: string shown = leader?.name ?? "nobody";
    string shown = leader != null ? leader.name : "nobody";
    Debug.Log("Leader: " + shown);
}

Với mọi thứ bắt nguồn từ UnityEngine.Object (GameObject, component, script của bạn), hãy kiểm tra bằng == null, != null hoặc if (obj), còn ?. và ?? thì dành cho các đối tượng C# thông thường như chuỗi. Cũng cần nhớ rằng Destroy chờ đến cuối khung hình mới thực hiện: cho đến lúc đó, đối tượng vẫn còn tồn tại và == null là false.

challenge icon

Thử thách

Trung bình

Ngăn lỗi của drone sau khi mục tiêu bị phá hủy.

  1. Trong Update(), thay cả hai dòng bằng if (target != null), phép kiểm tra null của Unity.
  2. Bên trong câu lệnh đó, viết transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);.

Nhấn Chơi: drone đuổi theo mục tiêu, sau đó dừng lại mà không có lỗi nào trong Console. Sau đó nhấn Kiểm tra.

Tự làm thử

using UnityEngine;

public class Chaser : MonoBehaviour
{
    [SerializeField] private Transform target;
    [SerializeField] private float speed = 2f;

    void Start()
    {
        Destroy(target.gameObject, 2f);   // target sẽ bị hủy sau 2 giây
    }

    void Update()
    {
        Vector3 goal = target?.position ?? transform.position;
        transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
    }
}

Tất cả bài học trong Những kiến thức cơ bản về lập trình trong Unity

Tự luyện tập: Playground Unity