Best Practices: Where to put the instantiated input object?

Hi,
I’m trying to figure out a proper software architecture for my adventure game. It’s quite simple on the surface:

  • the player can be walking around and interacting with objects, or
  • a (modal) menu screen can be open (inventory, main menu etc)

I’m attempting this with the new input system. The core thing I’m struggling with is: where do I put the object generated by the input system API?

I’ve got two of them so far: PlayerControls for moving around, and MenuControls for the modal menu. I’d like to be able to enable/disable a control scheme from anywhere in my code, as needed (for example, I don’t want the player to move around in the world while a menu is open).

There’s an issue here:

  • If I instantiate e.g. PlayerControls locally in each MonoBehaviour that needs to register an event, I can’t enable/disable the control scheme globally anymore, because each instance of PlayerControls tracks its enabled/disabled state individually.
  • If I have the control scheme somewhere in a global/static variable, I can enable and disable it, but it will inevitably run into a memory leak, because the game objects remain as input event listeners when they are destroyed (most notably when level changes). This isn’t an issue in the first solution, because the event sender and consumer belong to the same object and they’re garbage collected together.

Is it good practice to have the input objects as a static variable in general? Having them somewhere locally makes the enabling/disabling feature kind of pointless. Or am I missing something?

Any advice on this topic would be much appreciated.

1 Like

This is a good question and I am too curious what would be the best practice.

The same thread exists in another subforum too (my bad), we had a lengthy but very insightful discussion about it there: