2D-массив объектов класса выдает ошибку: исключение нулевой ссылки: ссылка на объект не установлена ​​для экземпляра объекта - PullRequest
0 голосов
/ 22 января 2019

Я некоторое время не занимался кодированием, пытаясь заставить простой проект вернуть мою руку, и я застрял.

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 голосов
/ 22 января 2019

derHugo привел меня к ответу за то время, которое потребовалось, чтобы приготовить себе тост с арахисовым маслом.Путь к дерГюго!

Вот мой класс плитки.Ему не нужны были все вещи 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);
            }
        }
    }
}

Теперь она работает!

0 голосов
/ 22 января 2019

Ваш Tile относится к типу MonoBehaviour! MonoBehaviours нельзя создать как обычные классы, но только путем добавления их с помощью AddComponent к определенному GameObject; они не могут существовать без привязки к GameObject.

Поэтому ваша линия

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

на самом деле не создает заполненный массив с экземплярами со значениями по умолчанию, но вместо этого создает двумерный массив, заполненный null заполнителями для 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 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
                    };
            }
        }
    }
}

Но лично я всегда предпочел бы иметь правильный конструктор и имена полей (public => PascalCase)

[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;
    }
}

и с использованием

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++)
            {
                Tile[x, y] = new Tile(0,0,0,0);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...