(moved to unity scripting, please ignore)

Hello, I have designed a “grid system” storing positions for my enemies to move to. However, for some reason my methods seem unable to access the array or list inside of my main class. The array/lists are properly setup, a list.Count or array.Length check will show that they are both filled with elements, so they aren’t the problem. But for some bizarre reason these same checks (when used outside of the start function) return a 0, meaning no elements are in the array/list anymore? What happened here? I will add that I am using constructors, but again, I can find no issues with this constructor, it seems to build just fine. You can access any of the nodes within the start function, but from no where else. Please help!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// node that stores one space in the "grid" as well as its current vacancy (might be useless but it's there just in case)
public class Node
{
    private Vector3 position;
    private bool isOccupied;

    public Node(Vector3 newPos)
    {
        position = newPos;
        isOccupied = false;
    }

    public Vector3 GetPosition()
    {
        return position;
    }

    public bool IsVacant()
    {
        return !isOccupied;
    }
}

// creates a list of nodes, as well as a list of nodes that are currently free; also contains functions for managing these lists
public class GridController : MonoBehaviour
{
    private Node[] nodes;
    private List<int> freeNodes; // list of numbers from 0 to x, pick one at random and then plug it into nodes for a free position

    // Start is called before the first frame update
    void Start()
    {
        // the list of nodes and positions
        nodes = new Node[12];
        nodes[0] = new Node(new Vector3(-3.2f, -0.7f, 0.0f));
        nodes[1] = new Node(new Vector3(-1.3f, -0.7f, 0.0f));
        nodes[2] = new Node(new Vector3(1.3f, -0.7f, 0.0f));
        nodes[3] = new Node(new Vector3(3.2f, -0.7f, 0.0f));
        nodes[4] = new Node(new Vector3(-3.2f, -3.4f, 0.0f));
        nodes[5] = new Node(new Vector3(-1.3f, -3.4f, 0.0f));
        nodes[6] = new Node(new Vector3(1.3f, -3.4f, 0.0f));
        nodes[7] = new Node(new Vector3(3.2f, -3.4f, 0.0f));
        nodes[8] = new Node(new Vector3(-3.2f, -5.7f, 0.0f));
        nodes[9] = new Node(new Vector3(-1.3f, -5.7f, 0.0f));
        nodes[10] = new Node(new Vector3(1.3f, -5.7f, 0.0f));
        nodes[11] = new Node(new Vector3(3.2f, -5.7f, 0.0f));

        freeNodes = new List<int>();

        // add the (currently) free nodes to the other list
        for (int i = 0; i < 12; i++)
        {
            freeNodes.Add(i);
        }

        Debug.Log("Free nodes currently contains " + freeNodes.Count + " nodes.");

    }

    // public functions to be accessed by enemies and modify the free node list

    // will remove a given int from the list, meaning it's respective node is now "occupied"
    public void OccupyFreeNode(int num)
    {
        freeNodes.Remove(num);
    }
 
    // will add a given int to the list, meaning it's respective node is now free.
    // note: intended to recieve the enemy's stored int of its current node, meaning the list can never have duplicate numbers/etc
    public void FreeUpFreeNode(int num)
    {
        freeNodes.Add(num);
    }

    // will return a free position for an enemy while removing it from its list
    public int GetRandomFreeNode()
    {
        int temp;
        /*
        if (freeNodes.Count != 0)
            temp = freeNodes[Random.Range(0, freeNodes.Count)];
        else
            temp = -1; // intentional game breaking error to let me know i screwed up
        */
        Debug.Log("Free nodes currently contains " + freeNodes.Count + " nodes.");
        temp = freeNodes[Random.Range(0, freeNodes.Count)];
        OccupyFreeNode(temp);
        return temp;
    }

    // will return the Vector3 of the given index
    public Vector3 GetNode(int num)
    {
        Debug.Log("I tried to access " + num.ToString());
        return nodes[num].GetPosition();
    }

}

EDIT: Okay the above code definitely works, testing the methods inside of an Update() method functions perfectly. But for some reason it refuses to let other objects access the same lists using the same variables. See enemy code below.

Code looks fine to me. Where are you accessing it from?
Beware that if you want to access nodes from another MonoBehaviour in Start or Awake you could run into issues.

Another gameobject (enemy) accesses the GridController script via public inspector, but the GridController’s game object has been initialized well before the enemy accesses it.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyBrain : MonoBehaviour
{
    private bool scary; // can the enemy damage the player
    private int currentPos; // the current target/hover point for this enemy
    public float speed; // how fast can the enemy move into position?
    // public GameObject gridSystem; // the gameobject holding the script
    public GridController mothership; // just a nick name for the grid positioning system

    // Start is called before the first frame update
    void Start()
    {
        scary = false;
        // mothership = gridSystem.GetComponent<GridController>();
        currentPos = mothership.GetRandomFreeNode();
        Debug.Log("I just chose node " + currentPos.ToString());
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position, mothership.GetNode(currentPos), speed * Time.deltaTime);
    }

    // this has nothing to do with the problem at hand, this does nothing for now
    public bool IsScary()
    {
        return scary;
    }
}

It’s possible that the Start() method of EnemyBrain is called before the Start() of the GridController, which can lead to GetRandomFreeNode() producing an error. I would do the work in your GridController in Awake instead of Start.

Didn’t work, still bringing up a null exception on “return nodes[num].GetPosition();”

It’s impossible to help you without the full stack trace.

I’m… not sure what that is. Where can I get that?

If you look in the Unity Console where the error happened, it will show exactly how the error occured in the bottom half. Looks something like this:

It’s the part with the blue text. There you can see where the error occured exactly and maybe you’ll be able to find the culprit yourself :wink:

Sorry for the long delay, but I’ve been waiting moderator approval (for some reason)

Here are the errors and their respective stack trace, I couldn’t work anything out here. Their line positions may be slightly different, I’ve added a couple lines trying to sort out the problem with no dice.

Current code for ease of viewing:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// node that stores one space in the "grid" as well as its current vacancy (might be useless but it's there just in case)
public class Node
{
    private Vector3 position;
    private bool isOccupied;

    public Node(Vector3 newPos)
    {
        position = newPos;
        isOccupied = false;
    }

    public Vector3 GetPosition()
    {
        return position;
    }

    public bool IsVacant()
    {
        return !isOccupied;
    }
}

// creates a list of nodes, as well as a list of nodes that are currently free; also contains functions for managing these lists
public class GridController : MonoBehaviour
{
    private Node[] nodes;
    private List<int> freeNodes; // list of numbers from 0 to x, pick one at random and then plug it into nodes for a free position

    // Start is called before the first frame update
    void Awake()
    {
        // the list of nodes and positions
        nodes = new Node[12];
        nodes[0] = new Node(new Vector3(-3.2f, -0.7f, 0.0f));
        nodes[1] = new Node(new Vector3(-1.3f, -0.7f, 0.0f));
        nodes[2] = new Node(new Vector3(1.3f, -0.7f, 0.0f));
        nodes[3] = new Node(new Vector3(3.2f, -0.7f, 0.0f));
        nodes[4] = new Node(new Vector3(-3.2f, -3.4f, 0.0f));
        nodes[5] = new Node(new Vector3(-1.3f, -3.4f, 0.0f));
        nodes[6] = new Node(new Vector3(1.3f, -3.4f, 0.0f));
        nodes[7] = new Node(new Vector3(3.2f, -3.4f, 0.0f));
        nodes[8] = new Node(new Vector3(-3.2f, -5.7f, 0.0f));
        nodes[9] = new Node(new Vector3(-1.3f, -5.7f, 0.0f));
        nodes[10] = new Node(new Vector3(1.3f, -5.7f, 0.0f));
        nodes[11] = new Node(new Vector3(3.2f, -5.7f, 0.0f));

        freeNodes = new List<int>();

        Debug.Log("node number 3's position is " + nodes[2].GetPosition());

        // add the (currently) free nodes to the other list
        for (int i = 0; i < 12; i++)
        {
            freeNodes.Add(i);
        }

        Debug.Log("Free nodes currently contains " + freeNodes.Count + " nodes.");

    }

    /* this works apparently
    void Update()
    {
        int lmao = GetRandomFreeNode();
        Debug.Log("I chose: " + lmao.ToString());
        FreeUpFreeNode(lmao);
    }
    */

    // public functions to be accessed by enemies and modify the free node list

    // will remove a given int from the list, meaning it's respective node is now "occupied"
    public void OccupyFreeNode(int num)
    {
        freeNodes.Remove(num);
    }
   
    // will add a given int to the list, meaning it's respective node is now free.
    // note: intended to recieve the enemy's stored int of its current node, meaning the list can never have duplicate numbers/etc
    public void FreeUpFreeNode(int num)
    {
        freeNodes.Add(num);
    }

    // will return a free position for an enemy while removing it from its list
    public int GetRandomFreeNode()
    {
        int temp;
        /*
        if (freeNodes.Count != 0)
            temp = freeNodes[Random.Range(0, freeNodes.Count)];
        else
            temp = -1; // intentional game breaking error to let me know i screwed up
        */
        Debug.Log("Free nodes currently contains " + freeNodes.Count + " nodes.");
        temp = freeNodes[Random.Range(0, freeNodes.Count)];
        OccupyFreeNode(temp);
        return temp;
    }

    // will return the Vector3 of the given index
    public Vector3 GetNode(int num)
    {
        Debug.Log("I tried to access " + num.ToString());
        return nodes[num].GetPosition();
    }

}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyBrain : MonoBehaviour
{
    private bool scary; // can the enemy damage the player
    private int currentPos; // the current target/hover point for this enemy
    public float speed; // how fast can the enemy move into position?
    public GridController mothership; // just a nick name for the grid positioning system

    // Start is called before the first frame update
    void Start()
    {
        scary = false;
        currentPos = mothership.GetRandomFreeNode();
        Debug.Log("I just chose node " + currentPos.ToString());
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = Vector3.MoveTowards(transform.position, mothership.GetNode(currentPos), speed * Time.deltaTime);
    }

    public bool IsScary()
    {
        return scary;
    }
}

5154509--510668--temp1.JPG
5154509--510671--temp2.JPG