In this lesson, you will learn how to break down rigid, "all-in-one" manager scripts by offloading their state and logic into modular ScriptableObject assets.
Identifying the Monolith
A monolithic system typically manifests as a single "God Script" (e.g., GameManager.cs) that holds everything: player health, inventory lists, input logic, and sound effects. While convenient initially, this creates hard dependencies; if the GameManager changes, every other script breaks. To refactor this, we look for data that should be persistent and logic that should be independent.
From Monolith to Architecture
The goal is to move state into ScriptableObject "Variables" or "Sets" and offload logic into "Actions" or "Strategies." Instead of the Player script calling GameManager.Instance.UpdateHealth(10), we flip the relationship. The Player now references a FloatVariable asset.
Consider this refactoring:
The Monolith (Before):
public class GameManager : MonoBehaviour {
public float playerHealth = 100f; // Hard-coded in one place
public void TakeDamage(float amount) {
playerHealth -= amount;
// Direct coupling to UI, Audio, etc.
}
}
The Decoupled Version (After):
We extract the health into a FloatVariable ScriptableObject. Now, the Player and UI both reference the same asset independently.
[CreateAssetMenu]
public class FloatVariable : ScriptableObject {
public float Value;
}
public class HealthComponent : MonoBehaviour {
public FloatVariable health; // Asset injected via Inspector
public void TakeDamage(float amount) {
health.Value -= amount; // Logic is now data-driven
}
}
Why This Matters
By extracting state into ScriptableObjects, you remove the need for FindObjectOfType or static singletons. Systems no longer need to know the GameManager exists. The HealthComponent simply needs a FloatVariable. You can now swap that variable for a "BossHealth" or "PlayerHealth" asset in the inspector without changing a single line of code. This modularity allows your systems to be tested in isolation and enables designers to tweak game data while the game is running without fearing that they’ll break the underlying logic.
Key Takeaway: Refactoring to a ScriptableObject architecture means shifting from "one object knows everything" to "many objects share data through decoupled references."