Help with Making A Variable Global in a Scene

The game I’m developing currently is basically a board game with hexagonal spaces, but what type of space they are is randomized, so I need to keep a 2D array of their positions and what’s on them. This variable needs to be instanced to the scene and not persist through scenes, and be able to have its value edited and have that changed throughout all of the other scripts that have referenced it. I’ve been looking online for a solution but what I’ve found so far has persisted through scenes or been unable to be edited. So far I’ve been using a GameManager script that contains this, and I’ve attached that to an empty GameManager object. However, when it comes to getting this array from other scripts, I haven’t figured out a good way to do it. I think that I could use GameObject.Find("GameManager").GetComponent<GameManagerScript>().hexagonIndex but I’ve had experience with programming before and that seems messy and bad practice. Is there any way that I could allow the hexagonIndex array variable to be accessed by other scripts in the scene, and when I change the value of hexagonIndex in one script, have it change in another? Could I use scriptable objects for this? (I’ve looked online and I’m not sure if they’re the best for this)

I would say that using GameObject.Find("GameManager").GetComponent<GameManagerScript>().hexagonIndex is kind of bad practice, but not that bad if you are using it correctly. If it was me making the game I wouldn’t feel to bad about using this line of code, you just have to make sure you only use it in the start method of each object as calling this line of code in the update method is going to chew resources. You can save off the resulting reference as a private variable in each script so that it doesn’t have to re-find the GameManager object each time you need it. To clarify, you need to cache the GameManager component: GameManager gm = GameObject.Find("GameManager").GetComponent<GameManagerScript>(); then grab the array out whenever you want to use it: gm.hexagonIndex. Don’t cache the array itself as it won’t be updated.
This will get you basically what you want but there are some improvements you could make as you see fit:

  1. Instead of calling GameObject.Find use GameObject.FindObjectOfType so that it finds the GameManager script directly, and so that it doesn’t get confused if another game object is accidentally named GameManager

  2. Wrap your 2D array in a class so that it is easier to modify from other scripts. Since a 2D array is a primative type in C# it is pass by value, so to modify it from another script you would have to do something like

        var hexArray = gm.HexagonIndex;
     //Modify hexArray
     gm.HexagonIndex = hexArray; //Save it back to the gameManager

Whereas if you were to use something like a list of lists List<List<GameObject>> then you could just modify it without having to save it back at the end, since Lists are classes and therefore pass by reference.

  1. You could make you GameManager a Singleton, where you save the reference to the GameManager as a static variable so that other scripts could access it statically instead of having to find a reference to the GameManager object by looking in the scene, replacing your GameObject.Find() call with GameManager.Instance()