2维Class对象数组给出错误:空引用异常:对象引用未设置为对象的实例

时间:2019-01-21 21:23:58

标签: c# unity3d

一段时间以来,我一直没有编写代码,试图让一个简单的项目重新投入我的工作,但我陷入了困境。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Dungeon : MonoBehaviour
{
    public Tile[,] map = new Tile[40, 40];

    void Start() {
        for (int y = 0; y < 40; y++) {
           for (int x = 0; x < 40; x++){
                map[x, y].ceiling = 0;
                map[x, y].northWall = 0;
                map[x, y].westWall = 0;
                map[x, y].floor = 0;
            }
        }
     }
 }

它不会运行,给我一个错误,提示:“ NullReferenceException:对象引用未设置为对象的实例”

我应该提到,Tile类只是天花板,northWall,westWall和地板的支架。它们都是整数,我依赖于隐式构造函数。这是代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tile : MonoBehaviour
{
    public int ceiling { get; set; }
    public int northWall { get; set; }
    public int westWall { get; set; }
    public int floor { get; set; }
}

2 个答案:

答案 0 :(得分:0)

您的Tile类型为MonoBehaviourMonoBehaviours不能像普通分类那样创建,只能通过使用AddComponent将它们添加到某个GameObject来创建;如果不附加到GameObject,它们将不存在。

因此,您的行

public Tile[,] map = new Tile[40, 40];

实际上创建具有默认值的实例的填充数组,而是创建一个由null 引用 strong>,而不是实例。

我想您想要的是:

瓷砖

Tile

// use this tag to make it 
// serializable and e.g. visiable in the inspector
[System.Serializable]
public class Tile
{
    // use fields instead of properties 
    // since also properties are not serialzed
    public int ceiling;
    public int northWall;
    public int westWall;
    public int floor;
}

但是我个人总是希望拥有适当的构造函数和字段名称(public => PascalCase)

public class Dungeon : MonoBehaviour
{
    public Tile[,] map = new Tile[40, 40];

    private void Start() 
    {
        for (int y = 0; y < 40; y++) 
        {
           for (int x = 0; x < 40; x++)
           {
                // For simple types like e.g. int, string etc there are default values
                // so the array would be filled with those values.
                // However your class Tile has the default value null
                // So you have to create Tile instances using the default constructor like
                map[x, y] = new Tile();

                // And than optionally give it values
                // though they will be 0 by default of course
                map[x, y].ceiling = 0;
                map[x, y].northWall = 0;
                map[x, y].westWall = 0;
                map[x, y].floor = 0;

                // or alternatively
                map[x, y] = new Tile()
                    {
                        ceiling = 0,
                        northWall = 0,
                        westWall = 0,
                        floor = 0
                    };
            }
        }
    }
}

并使用

[System.Serializable]
public class Tile
{
    public int Ceiling ;
    public int NorthWall;
    public int WestWall;
    public int Floor;

    public Tile(int ceiling, int northWall, int westWall, int floor)
    {
        Ceiling = ceiling;
        NorthWall = northWall;
        WestWall = westWall;
        Floor = floor;
    }
}

答案 1 :(得分:0)

derHugo使我自己做出了花生酱吐司面包所需的时间。 derHugo的出路!

这是我的Tile课。它不需要所有MonoBehavior东西,我按照建议添加了一个构造函数:

public class Tile
{
    public int ceiling { get; set; }
    public int northWall { get; set; }
    public int westWall { get; set; }
    public int floor { get; set; }

    public Tile(int c, int n, int w, int f)
    {
        ceiling = c;
        northWall = n;
        westWall = w;
        floor = f;
    }
}

这是使用Tile类的函数:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Dungeon : MonoBehaviour
{
    public Tile[,] map = new Tile[40, 40];

void Start()
{
    for (int y = 0; y < 40; y++) {
       for (int x = 0; x < 40; x++){
            map[x, y] = new Tile(0, 0, 0, 0);
            }
        }
    }
}

现在它可以运行了!