我试图在Update / Awake函数中创建我的GridData数据作为测试。但我似乎无法让我的构造函数工作。我是CSharp和Unity的新手。所以,我有点卡在这里。
GridData类
[System.Serializable]
public class GridData {
[System.Serializable]
public struct rowData{
public float[] colum;
}
public static int numRows =30;
public static int numColums =20;
public rowData[] rows = new rowData[numRows];
//
//Constructor
public GridData(int x, int y){
numRows =y;
numColums = x;
rowData[] rows = new rowData[numColums];
}
}
FactalMapData类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FractalMapData : MonoBehaviour {
public int gridWidth =20;
public int gridWHight =20;
public GridData fractalGrid ;
void Update () {
//TEST
fractalGrid =new GridData(gridWidth,gridWHight);
Debug.Log ("row" + fractalGrid.rows.Length); //Object reference not set to an instance of an object
Debug.Log ("colum" + fractalGrid.rows[0].colum.Length);//Object reference not set to an instance of an object
}
}
答案 0 :(得分:1)
您永远不会在代码中的任何位置初始化public float[] colum;
。
因此,当您调用构造函数时,虽然您正确地创建了一个初始化的rows
数组,但每个colum
实例的rowData
字段尚未初始化并将抛出null尝试访问集合的长度时引用异常。
答案 1 :(得分:1)
public GridData(int x, int y){
numRows =y;
numColums = x;
rowData[] rows = new rowData[numColums]; // BUG HERE
}
此处您声明了一个LOCAL变量rows
,其名称与名为rows
的实例字段相同。因此,实例字段rows
永远不会被分配。
你的意思是:
public GridData(int x, int y){
numRows =y;
numColums = x;
rows = new rowData[numColums];
}
答案 2 :(得分:1)
根据我的评论中的建议,我建议您在构建oop代码之前实际学习 oop。
但是,错误的学习并不是那么糟糕,所以在这里你做的是:
[System.Serializable] // not a mistake, but do you really need this?
public class GridData {
[System.Serializable]
public struct rowData{
public float[] colum;
}
// why are you using a struct with only one field in it
// do you really need a struct?
// PITFALL: you'll be wondering later on, why the values for numRows and numColums are the same for all instances
// Why? Because they are static! That means there are *not* instantiated
public static int numRows =30;
public static int numColums =20;
// You are initializing your rowData here
// and again in the constructor. What do you actually want?
public rowData[] rows = new rowData[numRows];
//
//Constructor
public GridData(int x, int y){
// As mentioned before:
// you are assigning instantiating values to static fields
numRows =y;
numColums = x;
// you are *defining* a local variable called rows and initializing it with an array of length numColums
// After we leave the constructor this get's lost
rowData[] rows = new rowData[numColums];
}
}
您应该考虑另一件事:为什么要创建类
如果你发现,你有充分的理由,问问自己班上的责任是什么。例如:它是否只保留一些数据,它是否提供任何抽象,它是否会操纵它拥有的数据,是否应该公开数据?
以下是可以工作的方式
然后你可以实现类
public class GridData {
// The concrete data doesn't have to be exposed
// let's make it private
private float[] data;
// let's use properties for this (= less code)
// get; means it's accessible as defined at the beginning (public)
// private set; means only the class it self can change these numbers
public int RowCount { get; private set; }
public int ColCount { get; private set; }
// I want to represent the data as a 2D grid so let's make a function
public float GetCell(int x, int y) {
// validate requests!
if(
x >= ColCount || x < 0
||
y >= RowCount || y < 0
) {
// don't be shy to throw exceptions!
// they communicate exceptional circumstances!
throw new ArgumentOutOfRangeException("Requested cell is not on grid");
}
return data[y * RowCount + x];
}
// I want the data to be set from outside
public float SetCell(int x, int y, float value) {
// excercise for you!
}
public GridData(int cols, int rows) {
RowCount = rows;
ColCount = cols;
this.data = new float[rows * cols];
}
}
请注意,有多种方法可以实现符合我制定的需求的类。