Не происходит подписка на событие в Start()

95
24 августа 2021, 04:30

Есть метод Build()

      public void Build(CellSerializable[,] matrix)
        {
            ClearMatrix();
            CellMatrix = new GameObject[matrix.GetLength(0), matrix.GetLength(1)];
            var width = 1.5f;
            var height = (width / Mathf.Sqrt(3f / 4f));
            for (int i = 0; i != matrix.GetLength(0); i++)
            {
                for (int j = 0; j != matrix.GetLength(1); j++)
                {
                    CellMatrix[i, j] = Instantiate(Cell);
                    var cellData = CellMatrix[i, j].GetComponent<CellData>();
                    cellData.Level = matrix[i, j].Level;
                    cellData.MaxLevel = matrix[i, j].MaxLevel;
                    cellData.IsEmpty = matrix[i, j].IsEmpty;
                    cellData.PlayerOwnerId = matrix[i, j].PlayerOwnerID;
                    if (j % 2 == 0)
                        CellMatrix[i, j].transform.position = new Vector3(i * height, j * width, 0);
                    else
                        CellMatrix[i, j].transform.position = new Vector3(i * height + height / 2, j * width, 0);
                }
            }
        }

В нем вызывается метод Instantiate() который создает объект префаба. У этого префаба есть компоненты CellData,CellRender,CellMouseControl.

В CellData, при изменении полей я генерирую событие изменения: OnChanged.

    public class CellData : MonoBehaviour
    {
        public delegate void DataStateHandler();
        public event DataStateHandler OnChanged;
        private int level;
        public int Level {
            get => level;
            set
            {
                level = value;
                OnChanged();
            }
        }
        private int maxLevel;
        public int MaxLevel
        {
            get => maxLevel;
            set
            {
                maxLevel = value;
                OnChanged();
            }
        }
        private int playerOwnerId;
        public int PlayerOwnerId
        {
            get => playerOwnerId;
            set
            {
                playerOwnerId = value;
                OnChanged();
            }
        }
        private bool isEmpty;
        public bool IsEmpty
        {
            get => isEmpty;
            set
            {
                isEmpty = value;
                OnChanged();
            }
        }
    }

В CellRender я подписал метод на это событие:

    public class CellDataRender : MonoBehaviour
    {
        private CellData cellData;
        private UnityEngine.UI.Text oText;
        private UnityEngine.UI.Text lText;
        private UnityEngine.UI.Text mlText;
        public GameObject LevelText;
        public GameObject MaxLevelText;
        public GameObject OwnerText;
        void Start()
        {
            cellData = this.GetComponent<CellData>();
            oText = OwnerText.GetComponent<UnityEngine.UI.Text>();
            lText = LevelText.GetComponent<UnityEngine.UI.Text>();
            mlText = MaxLevelText.GetComponent<UnityEngine.UI.Text>();
            cellData.OnChanged += ShowData;
        }
        private void ShowData()
        {
            lText.text = cellData.Level.ToString();
            oText.text = cellData.PlayerOwnerId.ToString();
            mlText.text = cellData.MaxLevel.ToString();
            if (cellData.IsEmpty)
            {
                lText.text = "";
                oText.text = "";
                mlText.text = "";
            }
        }
    }

После того как я создал объект путем Instantiate я пытаюсь обратиться к полям DataCell с целью изменить их значения, соответственно происходит вызов события OnChanged, но вылетает NullReferenceException, это значит, что на событие еще никто не подписан. Почему так происходит? Разве Instantiate() не вызывает методы Start() у всех компонентов?

Answer 1

При Instantiate(), происходит не Start(), а Awake(). Start() происходит перед первым Update() (то есть в следующем фрейме).

READ ALSO
При уничтожении обьекта подвисает игра на Unity

При уничтожении обьекта подвисает игра на Unity

При уничтожении игрового объекта Destroy(gameobject); подвисает на секунду играПричина этому проклятая библиотека A* Pathfinding Project Выключая главный...

106
Как обратиться к данным в Entity Framework

Как обратиться к данным в Entity Framework

В моемNet Core приложении я хранил данные в классе DataService

280
Вычисление координат в матрице

Вычисление координат в матрице

Есть 5x5 матрица квадратов в произвольной части экранаКак найти координаты (x, y) в центре каждого квадрата?

120
Передача данных из формы

Передача данных из формы

Передаю данные из первой формы во вторую Выдает ошибку: Ссылка на объект не указывает на экземпляр объекта

126