Hi,
I am a newbie in ECS and have an simple question to ask.
Here's some code
public class LogMouseInputSystem : IExecuteSystem
{
private GameContext _context;
public LogMouseInputSystem(Contexts ctx)
{
_context = ctx.game;
}
public void Execute()
{
if (Input.GetMouseButton(0))
{
_context.CreateEntity().AddDebugMessage("mouse button down");
}
}
}
Many samples code gives me above example, pass a context by constructor parameter, but I reviewed these samples entry point, they use the same _Contexts.shareInstance_ , same thing in _Pools.pool_ . why not I write following code for less typing?
public class LogMouseInputSystem : IExecuteSystem
{
public void Execute()
{
if (Input.GetMouseButton(0))
{
Contexts.sharedInstance.game.CreateEntity().AddDebugMessage("mouse button down");
}
}
}
use it by singleton instance directly, or if you want to limit that one system needs one context we can do it by this:
public class LogMouseInputSystem : IExecuteSystem
{
private GameContext _context;
public LogMouseInputSystem()
{
_context = Contexts.sharedInstance.game;
}
public void Execute()
{
if (Input.GetMouseButton(0))
{
_context.CreateEntity().AddDebugMessage("mouse button down");
}
}
}
any other situation I haven't considered? I need someone helps me to think overall.
Cheers
Passing argument into constructor is "dependency injection" principle, it makes code more flexible. For example - it allows having multiple systems of the same type referencing different contexts, which could be used for tests or minigames.
@c0ffeeartc thanks for your explanation, I know the "dependency injection". As I said, I was ECS newer, so...FYI, some other contexts can be passed for different purpose? Could you show me some samples? I will appreciate that.
You might want to use a different Contexts instance in different unity scenes, or to have separate contexts between server and client, or you might want to do unit testing, where you mock up a dummy Contexts instance and pass it to systems, or as @c0ffeeartc said, you might have a minigame within a game and want that to have it's own Contexts instance that is separate from the main game. There are many reasons why you might want multiple Contexts instances. If you use the singleton instance you are limiting yourself quite heavily. It's just better architecturally to pass the contexts in the ctor.
Using Contexts.sharedInstance creates a tight coupling to this class and the code cannot be reused. Passing in contexts lets you use multiple instances of that class in different scenarios and with multiple different instances of contexts. This becomes very obvious when you start writing your first unit test or integration test.
Rule of thumb:
Always prefer passing in the contexts. Only use Contexts.sharedInstance when there's no other way. This will lead to more flexible design and helps writing reusable code.
Most helpful comment
Using Contexts.sharedInstance creates a tight coupling to this class and the code cannot be reused. Passing in contexts lets you use multiple instances of that class in different scenarios and with multiple different instances of contexts. This becomes very obvious when you start writing your first unit test or integration test.
Rule of thumb:
Always prefer passing in the contexts. Only use Contexts.sharedInstance when there's no other way. This will lead to more flexible design and helps writing reusable code.