Best practice to create centralized Input Reader implementation

I’m currently working on a project where I want to implement a centralized input reader using the “new” Input-System. Right now i have to declare input actions in each script like that:

playerInputActions = new PlayerInputActions();

However, I’d like to be able to reference a global instance of the input actions. This way, I can enable or disable action maps based on events passed by state machines through SOs acting as middleman. I’m using SO events to keep managers and game objects independent and to maintain managers in a different scene that’s always loaded.

My current input system uses C# events and I’d like to keep it that way if possible.

I’ve been trying to find anything helpful to implement this for 4 days now, but I haven’t found any specific guides or examples on how to achieve this with the Unity Input System.

Could anyone point me in the right direction, please?

Are you familiar with the “Singleton” approach? Basically, you set up your “Input Reader” manager class as a MonoBehaviour, and include in it a public static “Instance” variable which provides access to an instance of that class (as a Component on a GameObject) in your scene. You can also get really fancy and “lazy load” the instance when you try to get it while it is null - by creating the new GameObject and adding the Component in the “get” block of your Instance property.

There are many approaches to creating Singleton structures, and none are truly an absolutely “correct” way, but what I’m describing above would look something like:

public class MyClass : MonoBehaviour
{
    private static MyClass instance;
    public static MyClass Instance
    {
        get
        {
            if (!instance)
            {
                instance = new GameObject("MyClass Singleton", typeof(MyClass)).GetComponent<MyClass>();
                instance.playerInputActions = new PlayerInputActions();
            }

            return instance;
        }
    }

    public PlayerInputActions playerInputActions { get; private set; }
}

Then you can just get a reference to your single PlayerInputActions from your single instance of MyClass via the Instance lazy-loader singleton, like so:

var theOneTruePlayerInputActions = MyClass.Instance.playerInputActions;

If you want to take it even further, you can expose delegates (Actions) in MyClass and have your other scripts subscribe those as your own custom input event callback layer, instead of directly exposing and accessing PlayerInputActions in every other class.

Ultimately it’s just whatever works and works best for you, specifically - but this should provide a basic starting point.