NullReferenceException array

I have a serious problem with this segment of code…the last part of it when I index through the array it always gives me NullReferenceException but I know the list isnt empty and my Cel class has a position and an h cost to it.

//testt.js

#pragma strict
 
class testt extends MonoBehaviour //// the representation of a GridCell made from Cells
{
    var agentTransform : Transform;
    var enemyTransform : Transform;
    var parentCell     : Cel;
 
    var lowestCost     : float;
 
    var list : List.<Cel> = new List.<Cel>();
 
 
    var cube    : Transform;
    var hit      : RaycastHit;
    var distance   : int = 10;
    var color       : Color;
 
    var v         : int ;//number of cells
    var i         : int;
    var x         : int;
    var c         : int;
 
 
    var cellSize   : int ;//cell size
    var cellSizeX  : int;
    var cellSizeZ  : int;
 
    var scale       : int;
    var cells      : Cel[,];//2d array ------ that ---- accepts only cells
    var cel      : Cel;
 
    var currentPos        : Vector3;
    var topLeftCorner  : Vector3;
 
 
 
 
 
 
    function Start()
    {
       lowestCost = Mathf.Infinity;
       v = 6;
       cellSize = 4;
 
 
       cel.obj    = agentTransform;
       cel.enemy  = enemyTransform;
       cel.color  = Color.red;
       scale = 2;
       topLeftCorner =Vector3 (transform.position.x-transform.localScale.x/scale ,transform.position.y  ,transform.position.z-transform.localScale.z/scale);
    }
 
    function Update()
    {  
 
 
       cells = new Cel[v,v];///the size of the 2d array
 
       cellSizeX = transform.localScale.x / cellSize;//width
       cellSizeZ = transform.localScale.z / cellSize;//height
 
 
       for(i = 0 ; i < v ; i ++)
       {
         for(x = 0 ; x < v ; x ++)
         {
 
          ////THE CURRENT POSITION AND TYPE OF CELLS////
          //print(x);
          currentPos = topLeftCorner + Vector3(i*cellSizeX,0,x*cellSizeZ); ////current position of the cell in i,x coordonates
          cells[i,x] = cel;////each of cells of coordonates [1,1] or cells[1,2] etc will equal one cell
          cells[i,x].celPos =currentPos;
          ////THE CURRENT POSITION AND TYPE OF CELLS////
 
 
 
 
          ////not good
 
          parentCell = cells[i,x].currentCellParent;//parrentCell = the first cell in the list
 
          ////not good
 
 
 
          //if(list != null)
          ///{
          //  list.Clear();
          //}
 
 
 
 
 
          ////ADD NEIGHBOUR CELLS////
 
          if(i+1 < v && x+1 < v)
          {
              if(!list.Contains(cells[i+1,x+1]))////this is better////but still not good////only if list contains the i+1,x+1 if not then add
              {
                 list.Add(cells[i+1,x+1]);////this is better////but still not good////only if list contains the i+1,x+1 if not then add
              }
          }
          if(i-1 > 0 && x-1 > 0)
 
          {
              if(!list.Contains(cells[i-1,x-1]))
              {
                 list.Add(cells[i-1,x-1]);
              }
          }
          if(i-1 > 0 && x+1 < v)
 
          {
              if(!list.Contains(cells[i-1,x+1]))
              {
                 list.Add(cells[i-1,x+1]);
              }
          }
          if(i+1 < v && x-1 > 0)
 
          {
              if(!list.Contains(cells[i+1,x-1]))
              {
                 list.Add(cells[i+1,x-1]);
              }
          }
          if(x+1 < v)
 
          {
              if(!list.Contains(cells[i,x+1]))
              {
                 list.Add(cells[i,x+1]);
              }
          }
          if(x-1 > 0)
 
          {
              if(!list.Contains(cells[i,x-1]))
              {
                 list.Add(cells[i,x-1]);
              }
          }
          if(i+1 < v)
 
          {
              if(!list.Contains(cells[i+1,x]))
              {
                 list.Add(cells[i+1,x]);
              }
          }
          if(i-1 > 0)
 
          {
              if(!list.Contains(cells[i-1,x]))
              {
                 list.Add(cells[i-1,x]);
              }
          }
          ////ADD NEIGHBOUR CELLS////
 
 
          //print(list.Count);
          ////THE LOWEST COST////
          for(c = 0 ; c < list.Count ; c++)
          {
              if(list != null)
              {
                 //list
 = cells[i,x];////????////
                     //print("abba");
                     Instantiate(cube,list[c].celPos,transform.rotation);
                     if(list[c].h < lowestCost)
                     {
                       lowestCost = list[c].h;
                     }
                  }
              }
              ////THE LOWEST COST////
     
     
              ////ADD THE LOWEST CELL TO LIST////
              if(agentTransform != null)
              {
                  if(cells[i,x].h == lowestCost && !agentTransform.GetComponent(pathFind).theOpenList.Contains(cells[i,x]))
                  {
                     cells[i,x].currentCellParent = cells[i,x];////not good
                     agentTransform.GetComponent(pathFind).theOpenList.Add(cells[i,x]);
                  }
              }
              ////ADD THE LOWEST CELL TO LIST////
     
     
     
              ////ADD THE FIRST CELL TO LIST////
              if(Physics.Raycast(cells[i,x].celPos , Vector3.up , hit,distance))
              {
                  if(hit.transform.tag == "agent" && hit.transform.GetComponent(pathFind).theOpenList.Count == 0)
                  {
                     hit.transform.GetComponent(pathFind).theOpenList.Add(cells[i,x]);
                     Instantiate(cube,cells[i,x].celPos,transform.rotation);
                     print(cells.length);
                  }
              }
                 Debug.DrawRay(cells[i,x].celPos,Vector3(0,10,0), cells[i,x].color);
              ////ADD THE FIRST CELL TO LIST////
     
             }
           } 
     
        }
    }
    
    


    //Cel.js
    
    #pragma strict
     
    class Cel ////the representation of a Cell
    {
     
        var h : float;
     
        var obj      : Transform;
        var enemy    : Transform;  ////the enemy and its distance
        var distance  : Vector3;   ////the distance from this cell to the enemy
        var celPos       : Vector3;   ////this cells position
        var color    : Color;   ////this cells color
     
        var availible  : boolean = true;
        var inList        : boolean = false;
        var trueT      : boolean = false;
        var road    : boolean = false;
     
        var object : boolean = false;
     
        var currentCellParent : Cel;//////the parent of this cell
     
     
        function Cel (position : Vector3, object : Transform,  enemyPos : Transform, parent : Cel, hCost : float)
        {
           h = hCost;
           celPos          = position;
           obj           = object; //the object(cellunit) from witch we get the object position, distance,color
           enemy           = enemyPos;
           currentCellParent     = parent;  //this is better
     
           if(enemy != null)
           {
             distance = obj.position - enemy.position;
             h        = distance.magnitude * 10;
           } 
        }
     
        function Update()
        {
     
        }
    }
    

The error only appears at runTime and I cant figure out why.....the error always directs me to the part where I try to access the h or position by indexing the list.I really need help.

This is kind of a long explanation. You aren’t creating your cells correctly. I’m sorry to say that, but there’s no way around it. It looks like you are trying to create one cell then clone it v*v times to create the entire grid. There’s nothing wrong with that idea, but you made Cel a reference type (as all classes are). What you are actually doing is creating one Cell. Then creating v*v references to the same cell. Every time you update that cell’s position, you are just changing the position of the original cell.

What you need to do is either:

  1. Make cell a value type which it probably should be to begin with. That is your best solution. Just change it to:

    class Cel extends System.ValueType
    

    that way when you clone it, you will actually copy all the information from one instance to the next.

  2. You can create a new instance of Cel for each square if you want. Then you just can’t clone it.

That should almost solve all your problems. You have a second problem also. This is what was actually causing your null reference.

if(i+1 < v && x+1 < v) {
   if(!list.Contains(cells[i+1,x+1]))////this is better////but still not good////only if list contains the i+1,x+1 if not then add
   {
      list.Add(cells[i+1,x+1]);////this is better////but still not good////only if list contains the i+1,x+1 if not then add
   }
}

This problems a little harder to see. cells[i+1 , x+1] is probably null on the first frame. You create the whole list of cells, but since Cel is reference type, the whole array initializes to null. Since you’re going through and creating the rows in order (the double for loops). cells[i+1 , x+1] won’t actually reference anything until you get to it in the loop (which won’t be until v+1) iteration later. Hence when you index them later. `list

` is still full of lots of nulls.  

I think your best solution is to create the whole grid in `Start()` and then just do your pathfinding checks in the `Update()`.  It doesn't look like your grid changes much frame to frame so its best to initialize once and be done with it anyway.  The other nice thing about using a value type for your `Cel` is you can't get a null reference.

    class testt extends MonoBehaviour //// the representation of a GridCell made from Cells
    {
        var parentCell     : Cel;
     
        var list : List.<Cel> = new List.<Cel>();
     
        var v         : int ;//number of cells
        var i         : int;
        var x         : int;
        var c         : int;
     
        var cellSize   : int ;//cell size
        var cellSizeX  : int;
        var cellSizeZ  : int;
     
        var scale       : int;
        var cells      : Cel[,];//2d array ------ that ---- accepts only cells
        var cel      : Cel;
     
        var currentPos        : Vector3;
        var topLeftCorner  : Vector3;
    
        function Start()
        {
           lowestCost = Mathf.Infinity;
           v = 6;
           cellSize = 4;
     
     
           cel.obj    = agentTransform;
           cel.enemy  = enemyTransform;
           cel.color  = Color.red;
           scale = 2;
           topLeftCorner =Vector3 (transform.position.x-transform.localScale.x/scale ,transform.position.y  ,transform.position.z-transform.localScale.z/scale);
    
           cells = new Cel[v,v];///the size of the 2d array
           cellSizeX = transform.localScale.x / cellSize;//width
           cellSizeZ = transform.localScale.z / cellSize;//height
           for(i = 0 ; i < v ; i ++)
           {
             for(x = 0 ; x < v ; x ++)
             {
     
              ////THE CURRENT POSITION AND TYPE OF CELLS////
              //print(x);
              currentPos = topLeftCorner + Vector3(i*cellSizeX,0,x*cellSizeZ); ////current position of the cell in i,x coordonates
              cells[i,x] = cel;////each of cells of coordonates [1,1] or cells[1,2] etc will equal one cell
              cells[i,x].celPos =currentPos;
              ////THE CURRENT POSITION AND TYPE OF CELLS//// 
              parentCell = cells[i,x].currentCellParent;//parrentCell = the first cell in the list
            }
          }
        }
     
        function Update()
        {  
           for(i = 0 ; i < v ; i ++)
           {
             for(x = 0 ; x < v ; x ++)
             {
                  //Now do all your checks and stuff.
             }
           }  
        }
    }
    
    class Cel extends System.ValueType {
    
        //Stuff
    }

I think there’s all kinds of things wrong in your script. To answer your question though,

I don’t see anywhere that you actually initialize a Cel object. Even when you create the list, allocating the space for Cels is different than creating a new Cel (by calling it’s constructor). Since a Cel is never constructed, by default it has no h value