Leveling Up Game State Management with a Scriptable Objects Manager in Unity
Introduction
You’ve learned about the power of Scriptable Objects in Unity for game state management. Now, let’s take that a step further with a Scriptable Objects Manager. This manager not only automatically loads all your Scriptable Objects but it’s also super easy to use across your project.
The Scriptable Objects Manager
The manager uses the Singleton Pattern, ensuring there’s only one instance of it in the game. This makes it an ideal candidate for managing the state across different scenes and gameplay elements.
public static ScriptableObjectsManager Instance;
void Awake() {
if (Instance != null && Instance != this) {
Destroy(this);
} else {
Instance = this;
}
}
Initializing Scriptable Objects
When the manager awakens, it auto-loads all Scriptable Objects of specific types, making them readily available for gameplay.
FloatObjects = Resources.LoadAll<FloatValue>("ScriptableObjects").ToList();
IntObjects = Resources.LoadAll<IntValue>("ScriptableObjects").ToList();
BoolObjects = Resources.LoadAll<BoolValue>("ScriptableObjects").ToList();
StringObjects = Resources.LoadAll<StringValue>("ScriptableObjects").ToList();
Here we’re using the Resources.LoadAll method that loads all assets in a folder or file at path
in a Resources folder.
So your Assets/Resources folder can look like this:
Getting and Setting Values
The manager provides two core methods for interacting with Scriptable Objects: GetScriptableObject<T>()
and SetScriptableObjectValue<T>()
. The former retrieves the object, while the latter sets its value.
public T GetScriptableObject<T>(string name) where T : ScriptableObject {
if (typeof(T) == typeof(FloatValue)) {
return FloatObjects.Find(item => item.name == name) as T;
} else if (typeof(T) == typeof(IntValue)) {
return IntObjects.Find(item => item.name == name) as T;
} else if (typeof(T) == typeof(BoolValue)) {
return BoolObjects.Find(item => item.name == name) as T;
} else if (typeof(T) == typeof(StringValue)) {
return StringObjects.Find(item => item.name == name) as T;
}
return null;
}
GetScriptableObject
Generics make this method super flexible. Pass the Scriptable Object type and the name, and it returns the corresponding object.
You can use switch statements here or also a dictionary based approach, this is just my implementation and it works perfectly fine for my game.
SetScriptableObjectValue
public void SetScriptableObjectValue<T>(string name, object value) where T : ScriptableObject {
if (typeof(T) == typeof(FloatValue)) {
FloatValue item = FloatObjects.Find(x => x.name == name);
if (item != null) {
item.runTimeValue = Convert.ToSingle(value);
item.initialValue = Convert.ToSingle(value);
}
}
else if (typeof(T) == typeof(IntValue)) {
IntValue item = IntObjects.Find(x => x.name == name);
if (item != null) {
item.runTimeValue = Convert.ToInt32(value);
item.initialValue = Convert.ToInt32(value);
}
}
else if (typeof(T) == typeof(BoolValue)) {
BoolValue item = BoolObjects.Find(x => x.name == name);
if (item != null) {
item.runTimeValue = Convert.ToBoolean(value);
item.initialValue = Convert.ToBoolean(value);
}
}
else if (typeof(T) == typeof(StringValue)) {
StringValue item = StringObjects.Find(x => x.name == name);
if (item != null) {
item.runTimeValue = value.ToString();
item.initialValue = value.ToString();
}
}
}
Just like the getter, the setter also utilizes generics. Pass the type, name, and new value to update the Scriptable Object.
Conclusion
The Scriptable Objects Manager adds a whole new layer of flexibility and organization to your game state management in Unity. It provides a centralized location for Scriptable Objects and a clean API for other scripts to interact with them by using the Singleton Pattern.
By integrating this manager into your Unity projects, you’ll streamline your game state management, making it more maintainable and scalable.