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. Dismiss Notice

Function gives NullReferenceException after running through succesfully once.

Discussion in 'Scripting' started by Barachiel, Sep 30, 2014.

  1. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    Hello everyone.

    In Unityscript, I have a function to pick a random string out of an array, and this function is called in a foreach loop, but it returns a NullReferenceException. I printed to the console to have a look, and it's running through the foreach loop once, picking the random string, and on the second go through it's giving me the error.

    This is the relevant parts of the code, with Module and ModuleConnector being scripts on an object and it's children, respectively:

    Code (JavaScript):
    1. import System.Collections.Generic;
    2. import System.Linq;
    3.  
    4. var modules  :  GameObject[];
    5. var startModule  :  GameObject;
    6.  
    7. var iterations       =   5;
    8.  
    9. function Start ()
    10. {
    11.    var startModule = Instantiate(startModule, transform.position +Vector3(0,40,0), transform.rotation);
    12.    var pendingExits = new Array(startModule.GetComponent(Module).GetExits());
    13.  
    14.    for (var iteration = 0; iteration < iterations; iteration++)
    15.    {
    16.      var newExits = new List.<ModuleConnector>();
    17.  
    18.      for(var pendingExit:ModuleConnector in pendingExits)
    19.      {
    20.        var newTag       =   GetRandom(pendingExit.connectorTags);
    21.          print(newTag);
    22.        var newModuleObject =   GetRandomWithTag(modules, newTag);
    23.        var newModulePrefab   :   GameObject = newModuleObject;   //This is to convert the object to a GameObject so I can access it's components.
    24.        var newModule     =   Instantiate(newModulePrefab);
    25.      }
    26.    }
    27. }
    28.  
    29. function GetRandom(randomArray:Array)
    30. {
    31.    return randomArray[Random.Range(0, randomArray.length)];
    32. }
    33.  
    34. function GetRandomWithTag(modules:GameObject[],tagToMatch:String)     //Fetches a random module that has matching tags
    35. {
    36.    var matchingModules   :   GameObject[];
    37.  
    38.    for(var i=0; i < modules.Length; i++)
    39.    {
    40.      if (modules[i].GetComponent(Module2).moduleTags.Contains(tagToMatch))
    41.      {
    42.        matchingModules[i] =  modules[i];   //This is the line that throws the exception.
    43.      }
    44.    }
    45.    return GetRandom(matchingModules);
    46. }
    47.  

    If it's relevant, this is the code for the GetExits() function in the Module script:

    Code (JavaScript):
    1. function GetExits()
    2. {
    3.     return GetComponentsInChildren(ModuleConnector);
    4. }

    I had something similar to this working a while back in C#, but I clearly need to catch up as far as Unityscript goes. I'd really appreciate the help if someone could point me in the right direction and let me know where I went wrong.
     
    Last edited: Sep 30, 2014
  2. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Code (CSharp):
    1. function GetRandom(randomArray:Array)
    2. {
    3.    return randomArray[Random.Range(0, randomArray.length)];
    4. }
    Shouldn't it be randomArray.length - 1?
    Random.Range(min, max) has min and max both inclusive, I believe.
     
  3. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    489
    "The returned value will never be max unless min equals max."

    From the documentation
     
  4. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    That is correct only when it is Random.Range(int, int).
    Which is true in this case.
    I did not know int and float Random.Range are different, my bad, thanks for pointing out my mistake!
     
  5. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    I had a look at that function earlier, when I was trying to figure out what was going on. GetRandom() works without any issues though, and the error isn't pointing at that line (though that's not always an accurate measure of the problem).
     
  6. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Then what line does it say it fails at?
    NullReferenceException means that a null value is being accessed.
    Either use the debugger, or just print every value (or at least it's size) and see where it get stuck.
     
  7. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    I added a note in the code detailing the line that throws the exception, but I probably should have mentioned this outside of the posted code, as well.
    It's here, in any case, the line inside the if statement:

    Code (JavaScript):
    1. function GetRandomWithTag(modules:GameObject[],tagToMatch:String)     //Fetches a random module that has matching tags
    2. {
    3.    var matchingModules   :   GameObject[];
    4.    for(var i=0; i < modules.Length; i++)
    5.    {
    6.      if (modules[i].GetComponent(Module2).moduleTags.Contains(tagToMatch))
    7.      {
    8.        matchingModules[i] =  modules[i];   //This is the line that throws the exception.
    9.      }
    10.    }
    11.    return GetRandom(matchingModules);
    12. }
     
  8. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    My bad, I did not notice that part.
    I am not much of a JS coder, but is it okay to access matchingModules before declaring matchingModules = new GameObject[modules.length] ?
     
  9. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    No worries, I didn't realize before posting the code that it'd be that subtle and difficult to notice. It doesn't exactly stand out.

    While your suggestion wasn't the problem, it was the catalyst for my changing things that led to a series of errors that, in the end, allowed me to figure it out. =P

    I'd forgotten that GameObject[], as a builtin array, had the size I initially set and that size wasn't inclined to change, so a majority of the entries in that array were null.

    I ended up making a normal array with a length of 0, then increased it's length by 1 for each module that had the correct tag, before assigning that module to the array.

    Thanks for all your help. =)
     
  10. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    Glad you managed to have it work :)