Есть метод 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() у всех компонентов?
При Instantiate(), происходит не Start(), а Awake(). Start() происходит перед первым Update() (то есть в следующем фрейме).
Сборка персонального компьютера от Artline: умный выбор для современных пользователей