Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Receiving messages from the PlayerInput component without using it

Discussion in 'Input System' started by GamesbyJP, Dec 6, 2019.

  1. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    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!
     
  2. Le-Capitaine

    Le-Capitaine

    Joined:
    Jan 23, 2014
    Posts:
    33
    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.

    Code (CSharp):
    1.  
    2.     public InputAction actionOne;
    3.     public InputAction actionTwo;
    4.     public InputAction actionThree;
    5.     public InputActionAsset inputActions;
    6.  
    7.  
    8.     void GetBindings (InputActionAsset actions, InputAction action, string mapActionString) {
    9.         /*
    10.         using an explicit string, but you can name your InputAction
    11.         the same and use that directly if you want
    12.         */
    13.         InputAction mapAction = actions.FindAction (mapActionString);
    14.         foreach (InputBinding b in mapAction.bindings) action.AddBinding (b);
    15.         action.Enable ();
    16.     }
    17.  
    18.     void InitActions (InputActionAsset actions) {
    19.         GetBindings (actions, actionOne, "Somewhere/Action One");
    20.         GetBindings (actions, actionTwo, "Somewhere/Action Two");
    21.         GetBindings (actions, actionThree, "Somewhere/Action Three");
    22.  
    23.         actionOne.performed += context => {
    24.             /*
    25.             I take it you don't need further context
    26.             since you got around fine with messages,
    27.             but while we're here, we can also grab and cast context.control
    28.             to get press and release events
    29.             */
    30.             DoActionOne ();
    31.         };
    32.     }
    33.  
    34.     void Start () {
    35.         InitActions (inputActions);
    36.     }
    37.  
     
    GamesbyJP likes this.
  3. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    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.
     
  4. Le-Capitaine

    Le-Capitaine

    Joined:
    Jan 23, 2014
    Posts:
    33
    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.
     
    GamesbyJP likes this.
  5. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    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.
     
  6. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    @XXXX-XXXX 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.
     
  7. Le-Capitaine

    Le-Capitaine

    Joined:
    Jan 23, 2014
    Posts:
    33
    This is ugly, silly and I'm not even sure it's the right way, but
    Code (CSharp):
    1.  
    2. actionOne.performed += context => {
    3.     UnityEngine.InputSystem.Controls.ButtonControl control = (UnityEngine.InputSystem.Controls.ButtonControl) context.control;
    4.     /*
    5.     From context.control you can get .wasPressedThisFrame
    6.     and .wasReleasedThisFrame
    7.     */
    8.     if (control.wasPressedThisFrame) ActionOneWasPressed ();
    9.     if (control.wasReleasedThisFrame) ActionOneWasReleased ();
    10.         };
    11.  
    From there on, I'm not quite sure. I know .cancelled instead of .performed also seems to work for button releases.
     
  8. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    Looks quite funky indeed ;)
    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!
     
  9. Le-Capitaine

    Le-Capitaine

    Joined:
    Jan 23, 2014
    Posts:
    33
    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.
     
  10. GamesbyJP

    GamesbyJP

    Joined:
    May 20, 2018
    Posts:
    62
    Haha well, we're both here to learn, and we're both slowly but steady drifting further away from being an idiot ;)