Receiving messages from the PlayerInput component without using it

Hello everyone!

I’m pretty new to the new input system, and still learning it.
The way I used it so far, is to give every gameObject that needs to read input from the Input Actions the component called PlayerInput.
I just learned that this is the wrong way to do things, since every PlayerInput component is ment to represent a player. But the PlayerInput component is easy to use, since the gameObject its attached to automatically receives messages like (in my case) onJump for example.

Now here comes my question:
I have a gameObject that needs to receive those same messages the PlayerInput component sends, without actually using the PlayerInput component. What’s the correct way to receive those messages?

Thanks in advance!

Ditching the message approach (which you may well have to do eventually), my method to keep to one PlayerInput thus far has been to set up the InputActions I wanted into the class proper, refer to the InputActionsAsset somewhere in the scene (eg the main game controller), copy the relevant actions’ bindings from the asset into the InputActions, then finally hook up and enable the actions upon creation.

    public InputAction actionOne;
    public InputAction actionTwo;
    public InputAction actionThree;
    public InputActionAsset inputActions;


    void GetBindings (InputActionAsset actions, InputAction action, string mapActionString) {
        /*
        using an explicit string, but you can name your InputAction
        the same and use that directly if you want
        */
        InputAction mapAction = actions.FindAction (mapActionString);
        foreach (InputBinding b in mapAction.bindings) action.AddBinding (b);
        action.Enable ();
    }

    void InitActions (InputActionAsset actions) {
        GetBindings (actions, actionOne, "Somewhere/Action One");
        GetBindings (actions, actionTwo, "Somewhere/Action Two");
        GetBindings (actions, actionThree, "Somewhere/Action Three");

        actionOne.performed += context => {
            /*
            I take it you don't need further context
            since you got around fine with messages,
            but while we're here, we can also grab and cast context.control
            to get press and release events
            */
            DoActionOne ();
        };
    }

    void Start () {
        InitActions (inputActions);
    }
1 Like

Thanks for the reply! While the messages approach is sufficient enough for the scope of the project I’m working on, this certainly comes in handy. I do have a question about it, however.

What is the mapActionString ment to be used for? The string “Somewhere/Action One” for example.

That’s (as far as I know) the way of getting actions from an input action asset. The format is actionsAsset.FindAction ("<Action Map>/<Action Name>") or just actionsAsset.FindAction ("<Action Name>") if you’re not worried about action maps.

1 Like

Oh right, thank you!
If I don’t find a way to do it with messages I’ll definitely use your approach!
If somebody knows a way without ditching the message system altogether, suggestions are still welcome ofcourse.

@Le-Capitaine How would one go about getting the press and release events from context.control? I’ve searched through the documentation, but couldn’t find an answer to my question.

This is ugly, silly and I’m not even sure it’s the right way, but

actionOne.performed += context => {
    UnityEngine.InputSystem.Controls.ButtonControl control = (UnityEngine.InputSystem.Controls.ButtonControl) context.control;
    /*
    From context.control you can get .wasPressedThisFrame
    and .wasReleasedThisFrame
    */
    if (control.wasPressedThisFrame) ActionOneWasPressed ();
    if (control.wasReleasedThisFrame) ActionOneWasReleased ();
        };

From there on, I’m not quite sure. I know .cancelled instead of .performed also seems to work for button releases.

Looks quite funky indeed :wink:
But hey, if it works it works! I found out about the .cancelled property while searching through the docs, and I must say that it works for me to set a gamepad trigger to 0, and that’s why I was asking. Thanks!

Don’t thank me, I’m an idiot. I only just realised you can simply put UnityEngine.InputSystem.Controls into a using directive and then type just ButtonControl into your callbacks.

Haha well, we’re both here to learn, and we’re both slowly but steady drifting further away from being an idiot :wink: