I’ve made a few databases in my game, created using scriptable object. Basically the databases are just a generic class with a List field uses to store data. Using a custom editor, I generate a new ‘database’ file which is then located in this folder - “Assets/Database”.
I have a gameobject with a singleton script component attached, called ‘Game Manager’. I also have another script component attached (named “Database Manager”) to the same gameobject that contains my Game Manager script. The database manager just has a number of public variables used to store my database files generated from my customeditor. This is simply to have a central place that all my scripts can access the various databases files if they need to. I have just dragged my database files from the folder, into the inspector slots in the Database Manager script.
Everything works fine in the editor. However, when I build the game and run the .exe file, I keep getting null reference exceptions. Looking at the output log file, I believe it has to with the database references stored in the Database Manager script. I think that for some reason they are not there once i build the application? Do I have to manually load these database files from the folder when the application starts, and assign them manually in the Database Manager script? What am I doing wrong here?
Ok I figured this one out. For those of you interested, read on.
The problem was relating to the singleton class. The singleton script adds a new gameobject with a GameManager script component to the scene, if no instance of the GameManager already exists in the scene. In the editor, my scene always had a gameobject with the GameManager script present, and as mentioned above, the GameManager gameobject also had a database manager script attached. So while in the editor, I always had the scripts i needed in the scene all the time and didn’t have a problem when i clicked play.
When I build the game, the gameobject containing the GameManager script is not present, and hence it will create an instance of itself as it should. What it wasn’t doing however, was creating the database manager script along with it. So long story short, I created a prefab of my ‘GameManager gameobject’ and wrote some code to instantiate this gameobject if no GameManager was present. Basically exactly as per the Unity “Roguelike” tutorial here: Level Generation - Unity Learn. It was a great help.
Hope this helps anyone who may encounter the same problem.
If you put your GameManager scriptable object in your Resources folder, you won’t need a GameObject prefab that wraps it. You simply back it with a lazy singleton. Here’s an example from our project, the GameConfig. We’ve created an instance, and put it under Resources/Configs/GameConfig.
public class GameConfig : ScriptableObject {
public GameObject tooltipDisplayerPrefab;
// and a bunch of other prefabs
private GameConfig _config;
public static GameConfig config{
get {
if (_config == null)
_config = Resources.Load("Configs/GameConfig") as GameConfig;
return _config;
}
}
}
You can use it directly like this:
public class Example : MonoBehaviour {
void OnTriggerEnter(Collider other) {
GameObject prefab = GameConfig.config.tooltipDisplayerPrefab;
Instantiate(prefab, transform.position, Quaternion.identity);
...
}
}
No other code is required to make it work. The scriptable object will be included in builds as it’s put in the resources folder, and it will be loaded the first time you ask for something in it. No GameObject’s that will clutter your scene is needed.