Использование нулевого распространения для объектов единиц (от которых унаследованы ваши компоненты неверно ), поэтому Resharper не предлагает этого делать, но Visual Studio 2019 фактически выдает предупреждение об этом.
Почему он предлагает для IDamageable
хотя? потому что это интерфейс, а IDE (редактор кода) не знает, какой тип объекта представляет этот экземпляр интерфейса до времени выполнения.
Так что он позволяет это (или не предупреждает об этом, но во время выполнения его распространение выиграло ')не работает должным образом), потому что интерфейсы не наследуются от UnityEngine.Object
, очевидно, но ForceVelocityCalculator
наследуется от MonoBehaviour
или ScriptableObject
, у которых UnityEngine.Object
в качестве конечного родителя, который отменяет проверку нуля, что означает распространение нуляязык C # - это не то же самое, что проверка нуля для объектов единиц, потому что единица отменяет проверку нуля.
Unity делает что-то особенное с оператором ==
. Вместо того, что большинство людей ожидают (на языке C # для не UnityEngine.Object
объектов), Unity имеет специальную реализацию оператора ==
.
Это служит двум целям:
Когда у MonoBehaviour
есть поля, только в редакторе Unity устанавливает для этих полей значение «реальный ноль», а не объект «фальшивый ноль». и пользовательский оператор ==
может проверить, является ли что-то одним из этих поддельных нулевых объектов, и ведет себя соответственно.
- Хотя это экзотическая установка, она позволяет единице хранить информацию в поддельном нулевом объекте, который дает вам больше контекстной информации, когда вы вызываете метод для него или когда вы запрашиваете у объекта свойство,
- Без этого трюка вы бы получили только
NullReferenceException
, трассировку стека, но вы не знали бы, что у GameObject
было MonoBehaviour
с полем, равным нулю. С помощью этого трюка Unity может выделить GameObject
в инспекторе, а также может дать вам больше указаний: «похоже, что вы получаете доступ к неинициализированному полю в этом MonoBehaviour
здесь, используйте инспектор, чтобы заставить поле указывать начто-то ».
Когда вы получаете объект ac # типа GameObject
, он почти ничего не содержит. это потому, что Unity - это движок C / C ++. Вся фактическая информация об этом GameObject
(его название, список компонентов, его HideFlags
и т. Д.) Находится на стороне c ++. Единственное, что имеет объект c # - это указатель на нативный объект.
- Вы можете называть эти объекты c # «объектами-обертками». Время жизни этих объектов c ++, таких как
GameObject
и все остальное, что происходит от UnityEngine.Object
, явно управляется. Эти объекты разрушаются при загрузке новой сцены. Или когда вы звоните Object.Destroy(myObject);
на них. - Время жизни объектов c # управляется способом c # с помощью сборщика мусора . Это означает, что возможно иметь объект обертки ac #, который все еще существует, который обертывает объект c ++, который уже был уничтожен. Если вы сравните этот объект со значением NULL, пользовательский оператор Unity == в этом случае вернет «true», хотя фактическая переменная c # на самом деле не является нулевой, , но нулевое распространение , скажет, что
UnityEngine.Object
все еще существует, когда его магистрали нет, это просто фасад, который все еще жив, надеюсь, это имеет смысл.
Источник