Reputation: 789
I'm trying to create my first bigger project in Unity and I am struggling to understand how abstract implementations away from the monobehaviour classes attached to gameobjects.
I am very familiar with dependency injection (using ASP.NET) but it seems DI is not a great idea to include in Unity projects according to a number of different articles. These articles say Unity has to handle Inversion of Control already, which is the Service Locator principal. I cannot find any built in implementation aside from methods like GameObject#Find
or GameObject#GetComponent
, etc.
An example would be a class handling interaction with files:
public interface IFileHandler { }
public class FileHandler : IFileHandler { }
public class FileHandling : MonoBehaviour
{
private IFileHandler fileHandler;
private void Awake()
{
this.fileHandler = new FileHandler();
}
}
Now the constructor of FileHandler
changes. I would have to change it in every class.
How can I decouple the FileHandler
from FileHandling
?
Thanks in advance
Upvotes: 0
Views: 212
Reputation: 2177
I recall that in Asp.net there's Program.cs
with main method that boots everything up. In unity you could have GameObject with similar Program.cs
script that has been assigned a very low Script Execution Order. The script simply initialises your game systems if they have not been initialised yet.
During initialization you can create system instances and store to a static class like toolbox from where you can later reference them from anywhere. If your system needs to listen to unity events like update you can create a new GameObject
with the script and set DontDestroyOnLoad
enabled and store it to the Toolbox as well.
Toolbox is basically singleton for storing your other "singletons" so they don't have to be singletons. If you use interfaces you can easily swap out the implementation for the SaveSystem for example.
// Enum to allow multiple instances if needed
enum GameSystems { SaveSystem, GameManager }
public class GameTB {
//usage GameTB.toolBox.SetTool(GameSystems.SaveSystem, new SaveSystem());
public static ToolBox<GameSystems> toolBox = new ToolBox<GameSystems>();
//usage GameTB.SaveSystem.SaveGame();
public static ISaveSystem SaveSystem
{
get
{
return toolBox.GetTool<ISaveSystem>(GameSystems.SaveSystem);
}
}
public static IGameManager GameManager
{
get
{
return toolBox.GetTool<IGameManager>(GameSystems.GameManager);
}
}
}
public class ToolBox<T>
{
private Dictionary<T, object> Tools { get; } = new Dictionary<T, object>();
public K GetTool<K>(T key)
{
if (Tools.ContainsKey(key))
return (K)Tools[key];
else
return default(K);
}
public void SetTool(T key, object tool)
{
if (!Tools.ContainsKey(key))
Tools[key] = tool;
else
Tools.Add(key, tool);
}
public bool ContainsTool(T key)
{
if (Tools.ContainsKey(key) && Tools[key] != null)
return true;
else
return false;
}
public void ClearTools()
{
Tools.Clear();
}
}
Upvotes: 1