-3

I am writing in Unity and not all classes can be instantiated as they inheriting Monobehaviour. I have several classes and am trying to Return an array to one class, but keep getting a null reference exception. I have made sure the array is indexed and initialized, yet it returns null. However in a same construction without an array, eg an Int, it works.

public class StartUp : MonoBehaviour  //Unity class
{
        public int x = 30,y = 30;
        public PlayField entireField;

        void Awake()
        {
            entireField = new PlayField(x,y);
            entireField.InitArray(entireField, x, y);
        }
}

public class CharacterController : MonoBehaviour
{
       //edit: playField is not supposed hold value, just to get
       //access to a method in PlayField
       PlayField playField; 

       FieldData fData;           

       void Start(){
           playField = new PlayField();
           fData = new FieldData();
       }
       void Update(){
          fData = playField.GetFieldData(5,6); //We're just telling it go to that method 
       } 
}
public class PlayField
{
       public SingleField[,] singleField;

       public PlayField()
       {

       }
       public PlayField(int x, int y)
       {
              singleField = new SingleField[x,y];
       }

       void InitArray(PlayField playfield, int x, int y){
              //In an effort to save the data I also did
              this.singleField = new SingleField[x,y];

              for(int j ...
              {
                  for (int x...
                  {
                      playfield.singleField[x, y] = new SingleField();
                      playfield.singleField[x, y].fielData = new FieldData();
                      playfield.singleField[x, y].fielData.height = GetRandom();
                      //and here
                      this.singleField[x,y] = new SingleField();
                      this.singleField[x,y].fieldData = new FieldData();
                  }
              }
              //to ..
              this.singleField = playfield.singleField;
       }

       public FieldData GetFieldData(int x, int y){

            //Here it keeps returning null reference
            return this.singleField[x,y].fieldData;
       }
}

public class SingleField
{
       public FieldData fieldData;
       public GameObject fieldObject;
}
public class FieldData
{
        public float height;
        public Vector3 position = new Vector3();
}

I know I can use a static variable but I'd like to know what I am doing wrong here or how I can get the values from entireField in StartUp class to the FieldData fData in CharacterController using the none-MonoBehaviour class PlayField? I thought the this.singleField-array would have values, but not during the Method call from CharacterController?

Erkan
  • 1
  • 3
  • 3
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Mateusz Aug 17 '17 at 12:18
  • You initialize `singleField` twice at `StartUp` and never in `CharacterController`. – Guy Aug 17 '17 at 12:20
  • @Guy Unity automaticly instantiates CharacterController when an 3D-object it is attached to is loaded in a scene, taken care of by MonoBehaviour. – Erkan Aug 17 '17 at 12:30
  • 1
    @Erkan It doesn't matter. `singleField` is never initialized in `CharacterController` but you are using it in `playField.GetFieldData(5,6);` In addition, not relevant to your question, `singleField` is initalized twice from `StartUp`. – Guy Aug 17 '17 at 12:33
  • @ m.rogalski I have made sure every element in the array is initialized though – Erkan Aug 17 '17 at 12:35
  • @Guy Yes, but I did that on purpose to only use it to get access to the GetFieldData method. It wasn't supposed to hold the values. Is there not a difference between this.singleField and the argument parameter? – Erkan Aug 17 '17 at 12:41
  • @Erkan no you have not and I can see that you haven't even use debugger. Mistake you've done can be spotted easily and was pointed out by _Guy_ in his comment. – Mateusz Aug 17 '17 at 12:50
  • @Erkan If you didn't initialize the array, it will be `null`. – Guy Aug 17 '17 at 12:52
  • @m.rogalski I was just doing that in case it was so. So I initialized the entire playField in Controller, all arrays [30,30] and all elements singleField[x,y] = new SingleField(); and all FieldData in the array ..[x,y].fieldData = new ... but still not? :/ Btw I am trying to get the field this.singleField-array in PlayField and not playField form Controller, those values should be 0. But if you guys don't see it thanks. – Erkan Aug 17 '17 at 13:09
  • What are talking about? This code just shows that you have no idea about OOP and programming in general. Inside of your `CharacterController` you initialize `playField` using default constructor which does not initialize it's member field `singleField`. Then you're trying to retrieve a value from that uninitialized member field. – Mateusz Aug 17 '17 at 13:13

2 Answers2

1

Erkan, I think you're going to need to take a step back and rethink how you're approaching this. Here's why I say that:

   //edit: playField is not supposed hold value, just to get
   //access to a method in PlayField
   PlayField playField; 

... that's not how things work. If you've got a 'main' PlayField that holds all your values, and initialize another one ... any time you call functions on that second one, it'll use the values from the second one. In your case, you're trying to call the GetFieldData function, which will grab field data from the second instance of PlayField - not the one you're going for.

So Where Do You Go From Here?

First, you might want to brush up a bit on Object Oriented Programming concepts. I'm not trying to be condescending - but it'll be hard to continue on with your program if you don't have a decent grasp on them.

Second, consider the use of 'static'. Static says, "I only have one instance of this throughout my program". Take the following for example:

class Playfield
{ /* code */ }

class SomeAlreadyExistingMainClassInYourCode
{
  static Playfield globalFieldInstance = new Playfield();
  /* rest of the class */
}

... at this point, you've got a single Playfield that's accessible throughout your program: SomeAlreadyExistingMainClassInYourCode.globalFieldInstance.

You shouldn't overuse/abuse this - but if you're only intending on having a single instance of an object being created, creating a static instance of it is a good way to do.

Kevin
  • 2,041
  • 7
  • 20
  • Even though I'm against using static data while working with Unity, your explanation to the problem is clear and for the beginner like Erkan should be somewhat a good start. – Mateusz Aug 17 '17 at 14:21
0

@m.rogalski Yes I was trying to avoid using a static too that's how this started.

Have solved the nullreference error. Really didn't think I had to initialize everything when I just wanted to use it only to call a method* in another class and use another instance of the same class for Return.

public class CharacterController : MonoBehaviour
{
   //edit: playField is not supposed hold value, just to get
   //access to a method in PlayField
   PlayField playField; 

   FieldData fData;           

   void Start(){
       playField = new PlayField();
       InitArray(playField,30,30);
       fData = new FieldData();
   }
  void InitArray(PlayField playfield int x, int y){
       playfield.singleField = new SingleField[x,y];
       for (int j =0; j< y;.. {
            for (int i..  {
                playfield.singleField[x,y] = new SingleField();
                playfield.singleField[x,y].fieldData = new FieldData();
            }
       }
  }
   void Update(){
      //The return was not supposed to be a field in this instance of
      //PlayField, but come from the PlayField class itself as 
      //this.singleField[x,y] (a array in PlayField)
      fData = playField.GetFieldData(5,6); //We're just telling it go to that method 
   } 
}

public class PlayField
{
    public SingleField[,] singleField = new SingleField[30,30];//evrything initailized and so on in the rest of the class here ommited. ect.

    public FieldData GetFieldData(int x,int y){
         //Here was the catch. Return values form this Class
         // and not read from the instance created in CharacterController
         //was giving me a nullrefence while I was using only FieldData
         return this.singleField[x,y].fieldData;
    }
}

This is solved for me. On to the next question. Thanks

Erkan
  • 1
  • 3