Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Assigning reference of an object doesn't work properly

Discussion in 'Scripting' started by Sachato, Jun 19, 2022.

  1. Sachato

    Sachato

    Joined:
    Dec 1, 2019
    Posts:
    3
    Hi,

    I have problem with references in Unity. I have created an object which is GameMaster- that Object on start creates most important objects on scene. Whenever i create some random unit object ( Line with comment `<<<<<<`) in Start() method of my GameMaster i can manipulate every parameter of that object through reference, and it seems to work, but whenever game leaves Start() method reference disappear, for example in Update() method im throwing Debug same way im doing in Start() method, and i have NullReferenceException: Object reference is not set to an instance of an object. Why it's happening, and how can i solve this?

    Code (CSharp):
    1. public class GameMaster : MonoBehaviour
    2. {
    3.     public GameObject empty;
    4.     public GlobalSettings globalSettings;
    5.     public GameObject tilePrefab;  
    6.     public GameObject brickPrefab;
    7.     public GameObject wallPrefab;
    8.     public GameObject chunk;
    9.     public GameObject[,] tileArray;
    10.     public GameObject UnitPrefab;
    11.     public int mapWidth;
    12.     public int mapDepth;
    13.  
    14.     public TileCoordinates unitCoordinates;
    15.     void Start()
    16.     {
    17.         int _backWidthOffset = mapWidth / 2;
    18.         int _backDepthOffset = mapDepth / 2;
    19.  
    20.         chunk = new GameObject();
    21.         chunk.name = "MapChunk";
    22.  
    23.         tileArray= new GameObject [mapWidth,mapDepth];
    24.        
    25.         for (int i =0; i<mapWidth;i++)
    26.         {
    27.             for (int j = 0; j < mapDepth; j++)
    28.             {
    29.                 Vector3 pos = new Vector3((i - _backWidthOffset) * tilePrefab.GetComponent<BoxCollider>().size.x,
    30.                                             0f,
    31.                                             (j - _backDepthOffset) * tilePrefab.GetComponent<BoxCollider>().size.z);
    32.                                            
    33.                 tileArray[i,j] = Instantiate(tilePrefab, pos, transform.rotation);
    34.                 tileArray[i,j].transform.parent = chunk.transform;
    35.                 tileArray[i,j].GetComponent<TileScript>().setCoordinates(i, j);
    36.                
    37.             }
    38.         }
    39.  
    40.         unitCoordinates = createRandomlyUnit();    /// <<<<<<
    41.         Debug.Log("CreateRandomlyUnit Outside ("+ unitCoordinates + ": " + tileArray[unitCoordinates.x, unitCoordinates.y].GetComponent<TileScript>().occupyingObject.transform.name);
    42.  
    43.     }
    44.  
    45.     // Update is called once per frame
    46.     void Update()
    47.     {
    48.         Debug.Log(unitCoordinates);
    49.         Debug.Log("CreateRandomlyUnit Outside (" + unitCoordinates + ": " + tileArray[unitCoordinates.x, unitCoordinates.y].GetComponent<TileScript>().occupyingObject.transform.name);
    50.     }
    51.  
    52.     public TileCoordinates createRandomlyUnit()
    53.     {
    54.  
    55.         TileCoordinates tcoords = transform.Find("Player").GetComponent<Player>().playerCoords;
    56.         int xx = Random.Range(0, mapWidth);
    57.         int yy = Random.Range(0, mapDepth);
    58.         while (tcoords == new TileCoordinates(xx, yy))
    59.         {
    60.             xx = Random.Range(0, mapWidth);
    61.             yy = Random.Range(0, mapDepth);
    62.         }
    63.         unitCoordinates = new TileCoordinates(xx, yy);
    64.         TileScript tScript = tileArray[xx, yy].GetComponent<TileScript>();
    65.        
    66.         Debug.Log("unit create on tile: " + tScript.tileCoords);
    67.         if(!tScript.isTileOccupied())
    68.         {
    69.             GameObject gObject = Instantiate(UnitPrefab, tScript.placeToStand.transform.position, transform.rotation);
    70.             tScript.setOccupyingObject(gObject);
    71.             tScript.occupyingObject.transform.name = "player";
    72.         }
    73.         Debug.Log("is tile occupied? ==> "+tScript.isTileOccupied());
    74.  
    75.         return new TileCoordinates(xx, yy);
    76.     }
    TileCoordinates just contain coordinates (x,y) of map, and TileScript is looks like this:


    Code (CSharp):
    1. public class TileScript : MonoBehaviour
    2. {
    3.     public float friction;
    4.     //public bool isOccupied = false;
    5.     public TileCoordinates tileCoords;
    6.     Material actualMaterial;
    7.     public GameObject label;
    8.     public Transform placeToStand;
    9.     public GameObject occupyingObject;
    10.     //public int x, y;
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         friction = 0.1f;
    15.         transform.gameObject.SetActive(true);
    16.         actualMaterial = transform.gameObject.GetComponent<MeshRenderer>().material;
    17.         occupyingObject=null;
    18.     }
    19.     public void setCoordinates(int i, int j)
    20.     {
    21.         tileCoords = new TileCoordinates(i, j);
    22.        // x = i;
    23.        // y = j;
    24.         label.GetComponent<Text>().text=i.ToString()+", "+j.ToString();
    25.     }
    26.     public void setOccupyingObject(GameObject occupyingGameObject)
    27.     {
    28.         Debug.Log("setOccupyingObject()"+tileCoords);
    29.         if (occupyingObject==null)
    30.         {
    31.             Debug.Log("setOccupyingObject()" + tileCoords);
    32.             this.occupyingObject=occupyingGameObject;
    33.         }
    34.         else
    35.             Debug.Log("Tile "+ tileCoords + " is already occupied!!!");
    36.  
    37.         Debug.Log("is occupyingObject of " + tileCoords + " true? " + isTileOccupied());
    38.         Debug.Log("name of occupied object is " + occupyingObject.name);
    39.     }
    40.     /*
    41.     * if there is object, then return true
    42.     * else false;
    43.     */
    44.     public bool isTileOccupied()
    45.     {
    46.         if (occupyingObject!=null)
    47.             return true;
    48.         else
    49.             return false;
    50.  
    51.     }
    52.     public override string ToString()
    53.     {
    54.         return tileCoords.ToString();
    55.     }
    56.  
    57. }
    I've made an object of Player on map, and i've add feature that when i click right mouse button on screen when it hits the tile via Raycasting i create some kind of object, and it works excelent there, and the reference is set properly i dont understand whats happening here in Start() method
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,958
  3. LaireonGames

    LaireonGames

    Joined:
    Nov 16, 2013
    Posts:
    696
    Its hard to help without the exact error. My guess is that its telling you line 49 is the error. In general you are being a bit dangerous logging like this because the log itself could produce null errors because you are using such a long chain:

    tileArray[unitCoordinates.x, unitCoordinates.y].GetComponent<TileScript>().occupyingObject.transform.name)

    tileArray, unitCoordinates, GetComponent, occupyingObject any of these could be null or return null. Try checking each one individually before logging this entire line.


    Also, this while loop looks nasty/dangerous and your future self would probably thank you if you rewrite it to be safer:

    Code (CSharp):
    1. while (tcoords == new TileCoordinates(xx, yy))
    2.         {
    3.             xx = Random.Range(0, mapWidth);
    4.             yy = Random.Range(0, mapDepth);
    5.         }
     
  4. Sachato

    Sachato

    Joined:
    Dec 1, 2019
    Posts:
    3
    Yes, i do know what is nullpointerexception. The problem is when my start method ends, the assigned reference ends also, and i don't know why its happening. Inside Start method i can easly operate on that reference, i can change name of an inatance of an object, i can manipulate however i want, but when start() ends im losing reference. I dont understand this and why its happening
     
  5. Sachato

    Sachato

    Joined:
    Dec 1, 2019
    Posts:
    3
    Yeee that while im going to fix, thanks for pointing it out. Anyway the problem here is that im using almost the same kind of reference to the same object, and when its inside start methos i can easly do this Debug, but when game leave start method im losing this reference, and Debug in Update method causing nullpointerException. I don't understand this