playMaker

Author Topic: Unity's (new) Input System  (Read 26444 times)

Thore

  • Sr. Member
  • ****
  • Posts: 480
Unity's (new) Input System
« on: May 05, 2019, 10:15:14 AM »
UPDATE prototype below no longer works, but Digitom made new actions here: https://hutonggames.com/playmakerforum/index.php?topic=21797.msg95729#msg95729

I was experimenting with Unity's new Input System, and can prototype with it (also have some actions that rely on another script), but look for ways to fetch the input data directly with custom actions rather than using a second script that needs to be adapted every time.

Out of the box, the Input System comes with a "Player Input" script that can send Unity events, messages, invoke, and probably more, but I couldn't find a way to make it talk to the FSMs, even though it can call SendEvent(), which would cover at least the simple button presses.

Had anyone success with it so far, or better yet, does anyone have actions for it? Thanks in advance :)



« Last Edit: July 28, 2020, 02:56:59 PM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15501
  • Official Playmaker Support
Re: Unity's (new) Input System
« Reply #1 on: May 17, 2019, 01:59:11 AM »
Hi,

 If you can send me a quick sample, I'll check it out and see how to integrate that.

Bye,

 Jean

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Unity's (new) Input System
« Reply #2 on: May 17, 2019, 05:58:29 AM »
Hi Jean, awesome!

I put my stuff into the prototyping thread I made (where I tried to figure it out myself). There is also an overview how it works, and a few resources of scripts/tutorials. Let me know how I can help.

https://hutonggames.com/playmakerforum/index.php?topic=20443.msg89661#msg89661

One thing I only tested later are the scripts mentioned above that Unity provides, called playerinput.cs (I think) and one to detect input from devices to automatically enable them (think couch multiplayer).

I can make an example scene and add that, too. (see below)
« Last Edit: May 19, 2019, 01:30:23 PM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Unity's (new) Input System
« Reply #3 on: May 19, 2019, 11:50:15 AM »
Alright, I made a simple scene to implement and test the new Input System, attached below.

Before, you'll need to install "Input System" (I used preview 0.2.8, current) to set it up.

There are two playable agents in there, both active at the same time, using all three binding types the new system provides.

I've set them up with the old method with super simple FSM each, just to see how they should work (in principle) under the new system. I also set up a corresponding (new system's) input action map, which of course right now does nothing. That should do the trick to test actions that somehow fetch the input from the new system, or so I hope :)



The action map is called "Play", and there are three actions.

Sideways, OnSideways
The capsule can move sideways with A/D keys, and also the arrow keys left/right using input.axis / input manager code. In the new input it would correspond to "1D axis", and I've called this action "Sideways".

Jump, OnJump
The capsule can also jump or flap around with space bar, which I've set up with button.down and standard "jump" mapping. The new system calls this a binding, and I've set an interaction to respond only to the press, and the action name is "Jump".

Directions, OnDirections
Finally, the circle is set to reading both horizontal and vertical axis in the old system, for which the new system would provide a 2D vector. I've set it up to listen to WASD and arrow keys. As you can see, the Action is called "Directions".

This is what it auto-generated from this (as found in "Input Actions.cs")

Code: [Select]
                Sideways.started += instance.OnSideways;
                Sideways.performed += instance.OnSideways;
                Sideways.canceled += instance.OnSideways;
                Jump.started += instance.OnJump;
                Jump.performed += instance.OnJump;
                Jump.canceled += instance.OnJump;
                Directions.started += instance.OnDirections;
                Directions.performed += instance.OnDirections;
                Directions.canceled += instance.OnDirections;

...

        void OnSideways(InputAction.CallbackContext context);
        void OnJump(InputAction.CallbackContext context);
        void OnDirections(InputAction.CallbackContext context);

One idea would be three actions, each one for each binding type (binding, 1D axis and 2D vector) and the user can provide the action name they've set up, i.e. Sideways, Jump and Directions in my example.

But then there's also the playerInput.cs that is provided with the input system. You can see it here. I've attached it, but have no idea how to make use of it.



Hope that helps. See the other post for some resources, and thanks a lot for looking into it. :)
« Last Edit: May 19, 2019, 01:33:02 PM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15501
  • Official Playmaker Support
Re: Unity's (new) Input System
« Reply #4 on: May 23, 2019, 04:38:06 AM »
Hi,

 Excellent, that will help me greatly! I can't promess when I am going to start on this, so please bump every week or so, just to keep me aware of that... I need it.

Bye,

 Jean

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Unity's (new) Input System
« Reply #5 on: May 31, 2019, 09:55:27 AM »
Bump, but also an almost-working example. I figured out how to get the Action from user-provided strings. It doesn't complain, but alas, doesn't trigger the action when an associated button is pressed. Maybe you (or someone else) can spot the problem :)

i.e. the OnEnter stuff works, but the OnUpdate etc doesn't do anything.

Code: [Select]
using UnityEngine;
using UnityEngine.InputSystem;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Input)]
public class InputGetBinding : FsmStateAction
    {

        [RequiredField]
        [Tooltip("Create an Input Action asset (right-click in project > create > Input Action) and plug it here.")]
        public InputActionAsset inputAsset;
       
        [RequiredField]
        [Tooltip("Name of the Action Map.")]
        public FsmString actionMap;

        [RequiredField]
        [Tooltip("Name of the Action (Binding). For other types use different Playmaker Actions.")]
        public FsmString actionName;

        // Get these from inputAsset, and provided strings.
        // InputActionMap inputActionMap;
        InputAction inputAction;

        // Then work with it...
        [Tooltip("Send this event if one of the associated inputs is pressed.")]
        public FsmEvent sendEvent;

        [Tooltip("Set to True if the button is pressed.")]
        [UIHint(UIHint.Variable)]
        public FsmBool storeResult;
       
        [Tooltip("Repeat every frame. Typically this would be set to True.")]
        public bool everyFrame;

        public override void OnEnter()
        {
            //  inputActionMap = inputAsset.GetActionMap(actionMap.Value);
            inputAction = inputAsset.GetActionMap(actionMap.Value).GetAction(actionName.Value);
           
            Debug.Log("On Enter: Action = " + inputAction);
        }

        public override void OnUpdate()
        {
            inputAction.performed += OnAction;
            inputAction.canceled += OnAction;

            // alternative
            inputAction.performed += context => DoTheAction();
            inputAction.canceled += context => DoTheAction();
        }


        public void OnAction(InputAction.CallbackContext context)
        {

            Debug.Log("OnAction did the Thing!");
        }

        // Alternative
        void DoTheAction()
        {
            Debug.Log("DoTheAction did it!");
        }


        public void OnDisable()
        {
            inputAsset.Disable();
            inputAction.Disable(); // one is redundant.
        }

        public void OnEnable()
        {
            inputAsset.Enable();
            inputAction.Enable(); // one is redundant.
        }


    } // class
} // namespace
« Last Edit: June 01, 2019, 04:34:11 PM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15501
  • Official Playmaker Support
Re: Unity's (new) Input System
« Reply #6 on: June 04, 2019, 04:00:11 AM »
Hi,

 On Update should not register DoTheAction at all, it should be done only once, and the work will be executed inside the  DoTheAction() method, in short you don't need OnUpdate at all

Bye,

 Jean

Thore

  • Sr. Member
  • ****
  • Posts: 480
Input System Actions [Beta]
« Reply #7 on: June 26, 2019, 03:08:06 PM »
Heureka. I made it. The hickup was in the way Playmaker actions work. My solution is to call enable On Enter, and disable On Exit. This way, the action should keep listening during the active state, and not listen when the state is not active. But I only have dangerous half-knowledge, so please anyone (looking at you, Jean ;)) who feels like it, chime in and improve :)

I've made three actions for all three current types (plus variants, see in the threads below):

GetBinding: is like Get Button and Get Key.
Get1dAxisComposite: is like Get Axis, Horizontal / Vertical
GetVector2Composite: new! Both axes, gets WASD, stick, dpad etc. It also automatically adjusts for diagonal inputs.

Beginner Crash Course Guide
Beware! These are Beta Versions for now. If you want to test them, here's how this works. The Input System is compatible with the older system (you can use both or keep using the old one).

(setup begins at 1:20)

Step 1: Install the Input System Package
You'll find it in the package manager (Window > Package Manager). It's currently in preview, and you need to fiddle with the options on top to show preview packages. In one case, it only worked after restarting Unity.

Step 2: Make an Input Asset
Your controls are now stored in a new asset file. This is nice because you can easily store it away, re-use it or share it. To make one, right-click in Project > Input Action. Name it, e.g. Controls. When you select it, note in the inspector that it generates a C# class. Right now, the path is a bit buggy. The correct path starts with a folder within assets, e.g. Scripts/Controls.cs (note the full file name).

Step 3: Make an Action Map
Doubleclick to open the asset. You probably have different controls in the pause menu, on the map screen or during the main game. The Action Maps, on the left column, are for that purpose. Start with one, say Play, to group actions during gameplay. Whatever name you give, you need to set the same name in the Playmaker actions.

Step 4: Create an Action
Now define an Action, for example Jump, and then you assign any number of keys or buttons to this action with the little plus button. Note what type you use, and use the corresponding Playmaker action later on. Create a new action for every action the player can perform. Note that by default, the binding register for both pressing and releasing (see next step). Tip: you can expand the Input Actions asset in the Project and see your Action Map and Actions easily, e.g. Controls > Play/Jump.

Step 5 (Optional):  Advanced
You can also create Control Schemes (upper corner) and then assign your bindings to any number of them. It's also possible to configure how the input is registered, e.g. button down, button up, etcetera and much more. You find the settings under Interactions. For Jump to only care about pressing, click on Interactions > Press. I advise reading better documentation than my quick crash course if you're interested in advanced features.

Cheers.

Attachments are down-thread.
« Last Edit: July 06, 2019, 07:56:13 AM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 480
Input System / New Binding Actions
« Reply #8 on: July 03, 2019, 10:50:01 AM »
A few more actions, all in BETA with the request that anyone who knows this stuff well chime in to improve :)

The new actions mimic current input actions (GetButtonDown, GetKeyUp etc), plus new ones:

Get Binding Down
Sends an event when the associated input (button, key etc) was pressed.

Get Binding Up
Sends an event when the associated input (button, key etc) was released.

Get Binding Hold
Doesn't have an event, but sets a bool value according to the input, true when pressed and false when released again.

GetBindingWithTimer
When the input is pressed/released (as configured in Input Actions asset) it sets the bool value to true, and after a given time (or on exit) sets it false again. This adds a grace period e.g. to jump buttons. When the player presses the button too early, before a new jump is possible, it can "remember" the press for a moment and execute the jump as soon as possible.

Make sure that you configure the buttons correctly in the Input Action asset. I haven't tested every possible permutation, but I assume that some combinations will not work (e.g. when the input is configured to only register the press, it should not work with the hold action etc).

Attachments are down-thread.
« Last Edit: July 04, 2019, 08:50:25 AM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 480
Input System / Notes
« Reply #9 on: July 03, 2019, 10:58:22 AM »
Listen Function
I noticed that when you bind using the "listen" button, it can bind slightly wrong inputs that will lead to errors.

For example, binding my controller with "listen" to a 1D composite creates leftStick[Gamepad], which however leads to an error that this expects a Vector2 composite binding. Indeed "leftStick" is the whole stick, both axes, thus Vector2. This can be easily fixed: the correct input is leftStick/<direction>. Another option is to actually use the Vector2 composite.

1D Composite Settings
By default, the setup doesn't work as probably expected. To make it work like an axis input (like GetAxis), you have to select the binding in your Input Actions asset, and add an Interaction to it, and set the "Trigger Behavior" to Press and Release.

Input Asset as Variable
Currently, the reference to the Input Action asset is established with the usual drag-and-drop or tiny circle. It might be neat if it was also possible to reference it via a variable, e.g. object type. Actually, when you press the small circle, you should see the Input Action asset right away. Afaik, a project only has one, so it's probably good the way it is.

For the Experts:
Here's an input script provided by the Unity team (from the Robbie demo). They cache input in update and clear it out in fixedupdate. Is this something that should be included somehow?

Code: [Select]
// This script handles inputs for the player. It serves two main purposes: 1) wrap up
// inputs so swapping between mobile and standalone is simpler and 2) keeping inputs
// from Update() in sync with FixedUpdate()

using UnityEngine;

//We first ensure this script runs before all other player scripts to prevent laggy
//inputs
[DefaultExecutionOrder(-100)]
public class PlayerInput : MonoBehaviour
{
public bool testTouchControlsInEditor = false; //Should touch controls be tested?
public float verticalDPadThreshold = .5f; //Threshold touch pad inputs
public Thumbstick thumbstick; //Reference to Thumbstick
public TouchButton jumpButton; //Reference to jump TouchButton

[HideInInspector] public float horizontal; //Float that stores horizontal input
[HideInInspector] public bool jumpHeld; //Bool that stores jump pressed
[HideInInspector] public bool jumpPressed; //Bool that stores jump held
[HideInInspector] public bool crouchHeld; //Bool that stores crouch pressed
[HideInInspector] public bool crouchPressed; //Bool that stores crouch held

bool dPadCrouchPrev; //Previous values of touch Thumbstick
bool readyToClear; //Bool used to keep input in sync


void Update()
{
//Clear out existing input values
ClearInput();

//If the Game Manager says the game is over, exit
if (GameManager.IsGameOver())
return;

//Process keyboard, mouse, gamepad (etc) inputs
ProcessInputs();
//Process mobile (touch) inputs
ProcessTouchInputs();

//Clamp the horizontal input to be between -1 and 1
horizontal = Mathf.Clamp(horizontal, -1f, 1f);
}

void FixedUpdate()
{
//In FixedUpdate() we set a flag that lets inputs to be cleared out during the
//next Update(). This ensures that all code gets to use the current inputs
readyToClear = true;
}

void ClearInput()
{
//If we're not ready to clear input, exit
if (!readyToClear)
return;

//Reset all inputs
horizontal = 0f;
jumpPressed = false;
jumpHeld = false;
crouchPressed = false;
crouchHeld = false;

readyToClear = false;
}

void ProcessInputs()
{
//Accumulate horizontal axis input
horizontal += Input.GetAxis("Horizontal");

//Accumulate button inputs
jumpPressed = jumpPressed || Input.GetButtonDown("Jump");
jumpHeld = jumpHeld || Input.GetButton("Jump");

crouchPressed = crouchPressed || Input.GetButtonDown("Crouch");
crouchHeld = crouchHeld || Input.GetButton("Crouch");
}

void ProcessTouchInputs()
{
//If this isn't a mobile platform AND we aren't testing in editor, exit
if (!Application.isMobilePlatform && !testTouchControlsInEditor)
return;

//Record inputs from screen thumbstick
Vector2 thumbstickInput = thumbstick.GetDirection();

//Accumulate horizontal input
horizontal += thumbstickInput.x;

//Accumulate jump button input
jumpPressed = jumpPressed || jumpButton.GetButtonDown();
jumpHeld = jumpHeld || jumpButton.GetButton();

//Using thumbstick, accumulate crouch input
bool dPadCrouch = thumbstickInput.y <= -verticalDPadThreshold;
crouchPressed = crouchPressed || (dPadCrouch && !dPadCrouchPrev);
crouchHeld = crouchHeld || dPadCrouch;

//Record whether or not playing is crouching this frame (used for determining
//if button is pressed for first time or held
dPadCrouchPrev = dPadCrouch;
}
}

Known Issue:
Gamepad Input only works in right and up directions.


« Last Edit: July 03, 2019, 01:35:09 PM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15501
  • Official Playmaker Support
Re: Unity's (new) Input System
« Reply #10 on: July 04, 2019, 03:56:32 AM »
Hi,

 This is great!! I think this should go on the ecosystem once the issues are ironed out, would you be ok with this?

Bye,

 Jean

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Unity's (new) Input System (Updated)
« Reply #11 on: July 04, 2019, 06:07:38 AM »
This is great!! I think this should go on the ecosystem once the issues are ironed out, would you be ok with this?

Sure, however, they aren’t ready yet (and I could use some expertise on the final stretches). After some more testing, I found that they can freeze up. The issue is likely with a conflict between the temporary nature of states, the type of code (which seems to not run all the time) and properly canceling and disabling inputs, which I don’t know how to resolve. I can write a script to fetch controls which doesn’t have the issue, but in Playmaker form, something causes a freeze when buttons are pressed frenetically. If you (or anyone) can help, check out get GetBinding.cs. Once I know how it's done, I'll adapt the remaining actions.

Important: there is still the Unity provided "Player Input" scripts (Add Component > Player...) which can send events! Maybe that's the way to go. But I haven't been successful to make them talk to Playmaker.

There is one definitive bug (#1) on Unity side of things (bug thread), the others are possibly user error and minor bugs that can be easily mitigated.
  • Gamepad currently doesn't return axes properly, only responds to positive values (up and right). It’s fixed, but not rolled out yet.
  • A freezing issue was reported by other users, too. Potentially the same “scripting mistakes” as mine above. It doesn’t happen with my regular script, though.
  • Minor: Input System needed a Unity restart after installation to work properly.
  • Minor: The input script that is generated is placed in an “asset” folder within the asset folder, but it allows to set a correct path.

UPDATE: As of Unity 2019.2 these actions NO LONGER WORK.
« Last Edit: September 01, 2019, 06:03:46 PM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Unity's (new) Input System
« Reply #12 on: July 18, 2019, 10:26:02 AM »
Jean bat signal as per ... ;)
so please bump every week or so, just to keep me aware of that... I need it.

Also, Brackeys made another video on the new Input System. Nothing new for me there, though I tried out his code variants, and they don't work with Playmaker at all.


EDIT: here's PlayerInput (script provided with the package)... not working with these settings.


« Last Edit: July 19, 2019, 10:35:00 AM by Thore »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15501
  • Official Playmaker Support
Re: Unity's (new) Input System
« Reply #13 on: July 19, 2019, 03:58:55 AM »
Hi,

 Cool, thanks for the bump :)

Bye,

 Jean

Broken Stylus

  • Beta Group
  • Hero Member
  • *
  • Posts: 716
Re: Unity's (new) Input System
« Reply #14 on: August 23, 2019, 01:42:14 PM »
What version of Unity are you working on Thore?