Null в Unity
Часть раздела Основы скриптинга в Unity путешествия по Unity на Coddy. Урок 60 из 85.
У объекта Unity есть две половины: объект C#, на который ссылается ваш скрипт, и объект движка за ним. Destroy(obj) удаляет половину движка в конце кадра, но ваша переменная по-прежнему указывает на половину C#, поэтому с точки зрения обычного C# это не null. Unity переопределяет ==, чтобы учесть это: после уничтожения объекта obj == null возвращает true, как и краткая проверка !obj. Это фальшивый null в Unity.
?., ?? и is null не используют этот ==. Они проверяют ссылку C#, которая всё ещё существует, поэтому вызов выполняется, а обращение к уничтоженному объекту вызывает исключение MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Эта метка показывает имя лидера гонки, которого могут выбить (уничтожить):
[SerializeField] private Transform leader;
void Update()
{
// вызывает исключение после уничтожения leader: string shown = leader?.name ?? "nobody";
string shown = leader != null ? leader.name : "nobody";
Debug.Log("Leader: " + shown);
}Для всего, что происходит от UnityEngine.Object (GameObject, компоненты, ваши скрипты), проверяйте с помощью == null, != null или if (obj), а ?. и ?? оставьте для обычных объектов C#, например строк. Также помните, что Destroy ждёт конца кадра: до этого момента объект всё ещё существует, и == null возвращает false.
Задание
СреднеОстанови ошибки дрона после уничтожения его цели.
- В
Update()замени обе строки наif (target != null)— собственную проверку Unity на null. - Внутри него напиши
transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);.
Нажми «Играть»: дрон преследует цель, а затем ждёт, и в Console нет ошибок. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
public class Chaser : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float speed = 2f;
void Start()
{
Destroy(target.gameObject, 2f); // цель уничтожается через 2 секунды
}
void Update()
{
Vector3 goal = target?.position ?? transform.position;
transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
}
}
Все уроки раздела Основы скриптинга в Unity
1Основы C# в Unity
Привет, UnityПеременныеДля дробных чисел нужна fТекст в консолиПеременные, которые запоминаютЕсли и иначеСравнение чиселПовторение: сборщик монет7Циклы и методы
Повторение с forЦиклы внутри цикловНапишите методМетоды, которые возвращают значениеМассивыПовторение: лестница10Поиск объектов
Поиск по имениТегиПоиск по типуСсылки лучше поискаNull в UnityПовторение: ближайшая монета13Проект: уворачиваемся от блоков
БегунБлоки с неба2Заставь двигаться
Размести кубДвигай каждый кадрПоворачивай каждую секундуУправляй клавишамиПовторение: веди куб5Векторы
Сложение векторовНаправленияЛокальное и мировое пространствоСкорость по диагоналиРасстояние между объектамиVector3 — это структураПовторение: пилот дрона8Игровые объекты и компоненты
Ссылки в InspectorПолучение компонентаОтсутствующие компонентыДобавление компонентаRequireComponentПоказ и скрытиеПовторение: выключатель светаПотренируйтесь самостоятельно: Песочница Unity