Can't access array from one script in another

Hi, I’ve been looking around on here quite a bit for help but this one I can’t seem to find the answer to; sorry if there is one which I didn’t find.

So I got a ‘GameManager’ Script which is where all the data is stored which is required by multiple scripts and will do other things later on.

public int questID = 1;
    public int[] journelQuests = {10,10,0,0,0,0,0,0,0,0,0,0};
    public static GameManager instance = null;

    void Awake()
    {
        //Check if instance already exists
        if (instance == null)
       
        //if not, set instance to this
        instance = this;
       
        //If instance already exists and it's not this:
        else if (instance != this)
       
        //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
        Destroy(gameObject);   
       
        //Sets this to not be destroyed when reloading scene
        DontDestroyOnLoad(gameObject);

    }

and I can successfully call from this the ‘questID’ and add use that in a different script but I can’t do the ‘journelQuests’.

the code I am using to use the array in the other script is here

void Awake () {


        for(int i = 0; i < 10; i++){

            jQ[i] = GameManager.instance.journelQuests[i];

            Debug.Log ("jQ = " + jQ[i]);

            if(jQ[i] == 0){

                jT[i].enabled = false;
                jT[i+1].enabled = false;

            }
            else
            {

                GetData ();

                jT[i].text = name;
                jT[i+1].text = desc;

            }

            i++;

            jQ[i] = GameManager.instance.journelQuests[i];

        }



    }

the error is - NullReferenceException: Object reference not set to an instance of an object

thanks for any help in advance and this is my first post so if I forgotten to state something or the format is wrong just say and I will happily rectify it.

Thanks

Isaac

Chance is that the second script Awake function is being called before the first.
Change it to use Start which follows after the Awake function.

Also on a programmer best practice note the formatting of your if/else statements is not nice…

indent them so its more like this:

if (instance == null)   
    instance = this;               
else if (instance != this)             
    Destroy(gameObject); 
    
DontDestroyOnLoad(gameObject);

Its easier to understand this way.

You are also mixing styles

if{
}
else
{
}

Pick a way to do your brackets and stick with it, dont mix styles it makes your code harder to read.

if
{
}
else
}
}

or

if{
}
else{
}

Hi Karl,

thank you for the quick response. I tried what you suggest but it didn’t work also thank you for pointing out those points about structure of code. The first one I didn’t realise my way made it hard for others to read, I’ve been doing it like that for ages in serval other languages but I will kept that in mind! The second one however I didn’t notice I was doing so I will keep an eye out for that in future.

Thanks

Isaac

Since you’re not using { } for your conditionals in the first script, it’s hard to tell if the blank lines and comments are ending them prematurely. Try changing removing the extra lines and comments from the first script and/or add braces.

void Awake()
{
    if (instance == null)
    {
        instance = this;
    }
    else if (instance != this)
    {
        Destroy(gameObject);
    }
    DontDestroyOnLoad(gameObject);

   }
}

You should also include the entire error and not just a single line with your interpretation of it.

Also, change this (if for no other reason than it sort of bugs me that I had to count these):

public int[] journelQuests = new[12]{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

Toss some Prints or Debug.Logs in there and test everything you can think of for null. This might be a problem with jQ rather than instance or journelQuests- hard to say without seeing the definition/initialization.

Hi Lysander,

sorry for the slow reply. The “void Awake” function is from the “RogueLike” example and it works fine there, I copied it and it fixed issues I was having earlier with the “questID” so I don’t think it’s that.

The entire error is this - NullReferenceException: Object reference not set to an instance of an object
JournelHud.Start () (at Assets/Scripts/JournelHud.cs:24)

I don’t know why I only copied part of it, I don’t think I was fully thinking straight :frowning:

Thank you for telling me how to declare the length of it; quite new to C#, didn’t really teach myself it in C++. Where would the definition/initialization be?

I’ve tried making it to show me the value of 0 in the array “jQ” and it didn’t show it, I put a value in and it fixed it; so thank you very much you are right! Now I got another issue which I could easily get around but it feels cheap and I want to learn how to use arrays better so if you don’t mind it would be great if you explain where I’m going wrong in doing the array declaration.

public int[] journelQuests = new[12]{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

when I put that line in it comes up with error -
Assets/Scripts/GameManager.cs(8,38): error CS0178: Invalid rank specifier: expected ,' or ]’

I got all the terminators on which is usually the cause of that error right? I’m quite new as you can tell.

Thanks

Isaac

Might be my fault, I usually don’t use inline initialization of int arrays like this. You may have to specify the array type for the constructor in the case that you define an array length rather than just letting it do it automatically- or you may not be able to define the length explicitly at all in this case…

EDIT: tested below

Works:

public int[] journelQuests = new int[12];
public int[] journelQuests = new []{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public int[] journelQuests = new int[]{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public int[] journelQuests = new int[12]{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

Doesn’t work:

public int[] journelQuests = new [12];
public int[] journelQuests = new [12]{10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

I would init an array with:

public int[] journelQuests = new int[12] { 10, ...};

I rarely use arrays since Lists provide a nicer abstraction:

public List<int> journelQuests = new List<int>() { 10, ... };

The speed difference should not be an issue in 99% of all cases, but Lists provide convenience like:

List.Add ( 2 );

As Karl pointed out you got your original error propably because the Awake functions were not called in the correct order (which points to bad code design by the way: variables that a script needs to work with should be included within the script itself, if possible) or because you missed to use the new keyword when creating the array.

Also notice that data-holding objects (like maybe your GameManager) don’t necessarily need to be MonoBehaviours, i.e. objects in your scene. If it only holds data you can do:

public class QuestData () { // no MonoBehaviour

    public List<int> qData = new List<int>() {};
  
    public void manipulateQuest ( string newQuest ) {}
}

and on your char class:

public class QuestCharacter : MonoBehaviour {

    private QuestData charQuests = new QuestData();

    void OnTriggerEnter ( Collider cTrigger ) {

        if ( cTrigger.tag == "QuestItem" ) {
            charQuests.manipulateQuest ( cTrigger.gameObject.name );
        }
    }
}

Ah okay thank you both of you, I’ll keep that in mind for the future. I’m quite new to this kinda of coding as I use to code in one document with no visuals. I am however slightly confused about the difference a “List” has to an “array” if someone could clarify that too, that would be great. Why is there a performance difference is my main question.

Thanks Isaac

Arrays are created as a contiguous block in memory all at once- you initialize them as a set length and then that length never changes- you can’t add to it or take away from it. Because it’s contiguous, iterating over the array takes very little effort- it’s lightning fast (no need to jump to memory location A in one spot then B in a completely different spot, and C back near where the first one was, etc…). A list, on the other hand, is better in situations where the size of the collection needs to be variable (or unknown at initialization time) and/or where you need a more dynamic control of the collection and the order of the items and such. An array is like lockers at at a school or gym, whereas a list is more like a stack of CD cases or something, and a dictionary is like a filing cabinet (or, you know, a dictionary ^_^). Everything has strengths and weaknesses.

A practical difference between an array and a list- if I want to remove “item 5” from an array, I can null a reference or set it to zero for an int, but I can’t remove it- that spot still exists. With a list, you can null or zero the contents, or you can remove the slot entirely so everything else drops down automatically and the length of the list is shortened by 1. It’s a far more fluid kind of structure.

Hope that helps!

Hi Lysander,

Okay I understand now! Thank you very much; I’ll keep that in mind for the future.

Thanks

Isaac