Array Elements aren't loaded until the object the script is attached to is selected in the hierarchy

Basically, I am making a system where the user can pick the amount of players in the game, then the controls they want to use (they do this by either clicking WASD,Arrow Keys, Left analogue stick, or Right analogue stick), and then their colour. However, the code runs fine when I’ve selected the object the script is attached to, but whenever I select another object, anything in my player control array isn’t loaded.
For this I have created a class here:

public class Players
    {
        public int playerNum;
        public int playerControl;
        public Color colour;
        public string name;
    }

And use this as the array:[SerializeField] public Players[] playerControlTemp;
This allows me to store all the details of the characters when I transfer to the next scene.
I’ve added this to debug:

 foreach (Players player in playerControlTemp)
                    {
                        Debug.Log(player.playerControl);
                        if (playerControlTemp[0] != null && player.playerControl == 0)

And whenever I select the object, I get the player controls, but when I’m selecting something else, I get “Object reference not set to an instance of an object”. If I select the object to load the array, then click off, it stills works. So clearly the issue is that unity isn’t loading the array until I have selected the object.
I am Initiating the array using this code from a separate script.

public void SelectNumOfCharacters()
    {
        settingManager.GetComponent<PlayerSettings>().playerControlTemp = new PlayerSettings.Players[numOfCharacters];

This is unbelievably annoying as there is no documentation on this, please help.

EDIT: The program doesn’t work on an executable, as nothing can be executed.
I have provided screenshots of my design.

Thanks

I’ll move your post to the General Scripting forum.

So you know, this forum is related to 2D specific post, not anything when making 2D game.

Thanks.

I’ll try to help but there’s not a lot of info to go off! Can you share the names of the classes and the relevant code from each?

Having said that, what exactly do you mean by

What object? What script? Which other object? What exactly happens when you select another object? What’s supposed to be in your player control array? How is it loaded? What’s that NullReferenceException that you keep getting? Is it relevant?

Is the issue to do with scene transitions? How are you handling that? Is it additive loading or persistent storage?

1 Like

Sounds like a bug to me! Welcome to debugging. Here’s a super-easy way to learn a LOT about your code:

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://discussions.unity.com/t/700551 or this answer for Android: https://discussions.unity.com/t/699654

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

When in doubt, print it out!™

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

You must find a way to get the information you need in order to reason about what the problem is.

The system is attached to the object “Player Settings”, this holds a static array of the class “Players”, called “PlayerControlStatic”, for the purpose of accessibility, I have created another copy of this but non-static called “PlayerControlTemp”. This is the code up until the error.

[SerializeField] public static Players[] playerControlStatic;
    [SerializeField] public Players[] playerControlTemp;
    public GameObject[] playerSelections;
    public GameObject[] colourSelections;
    public Sprite[] controlSprites;
    public bool isControlReady;
    public bool updateNumbers;

    public Color[] coloursToPickFrom;

    private int y;
    public bool isColourReady;
    public GameObject readyButton;

    public void Start()
    {
    }
    public void Update()
    {

        if (playerControlTemp.Length != 0)
        {
            for(int x = 1; x <= playerControlTemp.Length; x++)
            {
                string hName = "Horizontal" + x.ToString();
                string vName = "Vertical" + x.ToString();
                if (Mathf.Abs(Input.GetAxis(hName))>=0.45f || Mathf.Abs(Input.GetAxis(vName)) >= 0.45f)
                {
                    foreach (Players player in playerControlTemp)
                    {
                        Debug.Log(player.playerControl);
                        if (playerControlTemp[0] != null && player.playerControl == 0)

I know, its not very maintainable, but the issue isnt with the code, as the code works fine if the object “PlayerSettings” (The object which the script is attached to), is selected in the on runtime. If I click the button that allows this code to run through the if statement and the object is not selected, then it wont work, however if I pause then select it, come back and try again, it works.

Its almost as if the arrays data isn’t loaded until the source object is selected, might be a unity issue, either way, I’m going to try update my unity version and see if its a issue they have fixed in the newer versions, I’m usually pretty good with logical errors, but this seriously has my mind f******.

And to answer your question about what’s supposed to be in the player control array, this is what it looks like, when the object is selected and the code works as intended.
8448023--1120445--upload_2022-9-18_16-17-16.png

[SOLVED] I have found the issue with mine, well at least a temporary fix, when I declared the size of the array I used the following code:

public void SelectNumOfCharacters(int num)
    {
        playerControlTemp = new Players[num];
    }

I have changed it to this;

public void SelectNumOfCharacters(int num)
    {
        playerControlTemp = new Players[num];
        for(int x=0; x < num; x++)
        {
            playerControlTemp[x] = new Players();
        }
    }

No clue why it works, just does. But anyways thank you for your help :))

I haven’t looked through the rest of the code but the change is quite straight forward. When you initialise an array it will get populated with default values - in the class of a class - null. You’re solution is to actually assign values, which is correct.

The “Object reference not set to an instance of an object” exception is what you get when trying to use a null value

1 Like