Почему позже в скрипте массив объектов становится нулевым, даже после подтверждения того, что после инициализации он не равен нулю?

Название. где-либо еще в программе нет упоминаний о спрайтерендерерах или массиве

SpriteRenderer[,] Renderer = new SpriteRenderer[8,8];
    void Awake()
    {
        if (D)
        {
            D = false;
            for (int x = 0; x <= 7; x++)
            {
                for (int y = 0; y <= 7; y++)
                {
                    sq = Instantiate(square, globals.MovePos(x,y), Quaternion.identity);
                    Renderer[x,y] = new SpriteRenderer();
                    Renderer[x,y] = sq.GetComponent<SpriteRenderer>();
                    print(Renderer[x,y] == null);//false every time
                }
            }
        }
    }   
    void OnMouseDown()
    {
            if (stats.p != null)
            {
                stats.p.FindRange();
                for(int x = 0; x <= 7; x++)
                {
                    for(int y = 0; y <= 7; y++)
                    {
                        print(Renderer[x,y] == null); // true everytime
                    }
                }
            }
        }
    }
}

Что должно произойти, так это то, что он каждый раз печатает false.

Когда sq или любой из его родительских узлов будет уничтожен, компоненты станут нулевыми.

shingo 31.05.2024 06:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Первое, что вам нужно понять, это то, что Unity был написан на C++, и весь наш код C# — это не что иное, как оболочка для собственной логики Unity C++. Почти все объекты и методы Unity C# являются зеркалом собственного представления C++. Это поможет вам понять следующие строки.

SpriteRenderer наследуется от UnityEngine.Object класса, как и почти любой другой класс в пространстве имен UnityEngine. И UnityEngine.Object имеет переопределение для оператора сравнения (==). Вот из декомпилированного кода:


public class Object
{

...

    public static bool operator ==(Object x, Object y) => Object.CompareBaseObjects(x, y);

    private static bool CompareBaseObjects(Object lhs, Object rhs)
    {
      bool flag1 = (object) lhs == null;
      bool flag2 = (object) rhs == null;
      if (flag2 & flag1)
        return true;
      if (flag2)
        return !Object.IsNativeObjectAlive(lhs);
      return flag1 ? !Object.IsNativeObjectAlive(rhs) : lhs.m_InstanceID == rhs.m_InstanceID;
    }


    private static bool IsNativeObjectAlive(Object o)
    {
      if (o.GetCachedPtr() != IntPtr.Zero)
        return true;
      return !(o is MonoBehaviour) && !(o is ScriptableObject) && Object.DoesObjectWithInstanceIDExist(o.GetInstanceID());
    }

    internal static extern bool DoesObjectWithInstanceIDExist(int instanceID);
}

Как видите, для случаев, когда какой-либо из параметров равен null, существует определенная логика. В этом случае прямого сравнения не происходит, но происходит проверка состояния нативных объектов. Если собственный указатель объекта равен IntPtr.Zero, то есть является нулевым указателем (0x0), или указатель не является нулевым указателем, но указывает на уничтоженный объект, то результатом сравнения будет true. DoesObjectWithInstanceIDExist — нативная функция, поэтому мы не можем проверить, какая логика у нее под капотом, но, думаю, семантика этой функции довольно ясна.

До сих пор, если нативное представление вашего SpriteRenderer уничтожено, то сравнение с null вернет true. Это может быть вызвано вызовом метода Destroy(...), изменением сцены, уничтожением ее родителя и т. д.

Поэтому всегда нужно помнить, что ваша переменная НЕ null. Невозможно изменить значения переменных без прямого доступа к ним или их классам. Вы можете использовать Renderer[x,y] is null или System.Object.ReferenceEquals(Renderer[x,y], null), чтобы убедиться, что значение вашей переменной действительно равно null. А если это не null, вы все равно можете вызывать его методы. Опять же, все методы Unity имеют внутреннюю проверку состояния объекта и выдают исключение при вызове в таком состоянии. НО если у вас есть собственный класс, унаследованный от MonoBehavior и у него есть общедоступный метод, вы можете вызвать этот метод, даже если сравнение yourObject == null возвращает true. Поскольку уничтожение базового объекта C++ не приводит к уничтожению вашего объекта C#, оно просто заставляет оператор == работать по-другому.

Другие вопросы по теме

Похожие вопросы

C# XUnit (.Net 8): параметр IFormFile в конечной точке, подлежащей тестированию, всегда принимается как нулевой
Как я могу запускать метод через определенные промежутки времени? System.Timers.Timer, кажется, теряет синхронизацию
Почему игровой объект игрока продолжает двигаться в воздухе, несмотря на то, что клавиши движения не нажимаются? (закрыто)
Выполняется ли Dispose of my Activity синхронно с кодом моего приложения?
Привязка WPF MVVM DataGrid к IEnumerable вызывает ошибки привязки к Int32
Как избежать бесконечного цикла перенаправления при объединении двух разных схем аутентификации (openIdConnect и ASP.NET Identity)?
Добавьте несколько синглтонов одного и того же класса обслуживания во внедрение зависимостей в .NET 8
Универсальный способ извлечения значений тегов из XML-документа в список List<string>
Обновление .NET 8 ISOLATED прекратило регистрацию информации, отладки
MSAL AcquireTokenInteractive перенаправляет браузер на недоступный локальный хост