Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Create two virtual joysticks (touch) with the new input system

Discussion in 'Input System' started by Isaacg, Mar 24, 2020.

  1. Isaacg

    Isaacg

    Joined:
    Nov 17, 2013
    Posts:
    9
    Hi,

    I really like this new input system, but I'm having a hard time trying to actually know it.

    So, as the title says, I'm trying to create two virtual joysticks (one for aim, one for move).

    I have noticed that there's a script called On-Screen Stick, but looking inside I don't know how to send an event to an specific Controller/Action. Also, the output seems to be a little laggy.
    I'm selecting Touchscreen/Position, not sure if it's correct. Captura.PNG

    So, I guess my questions are:
    - Is it possible to configure an specific Controller (like MyLeftVirtualJoystick) inside InputActions (or wherever) and send events to it whenever I want?
    - How to properly use On-Screen Stick to make it less laggy and with two joysticks?

    Thanks!
     
  2. TubbyStubby

    TubbyStubby

    Joined:
    Nov 28, 2019
    Posts:
    6
    So this is what I did
    First created Input Action were Player is mapped to Move(value, vector2) with a binding Left Stick [Gamepad]

    and this in player controller script
    Code (CSharp):
    1. private Vector2 prevInput;
    2. private Controls controls;
    3.  
    4. private void Awake()
    5. {
    6.     controls = new Controls();
    7.     controls.Player.Move.performed += ctx => SetMove(ctx.ReadValue<Vector2>());
    8.     controls.Player.Move.canceled += ctx => ResetMove();
    9. }
    10.  
    11. private void OnEnable() => controls.Enable();
    12. private void OnDisable() => controls.Disable();
    13.  
    14. private void Update() => Move();
    15.  
    16. private void SetMove(Vector2 moveInput) => prevInput = moveInput;
    17. private void ResetMove() => prevInput = new Vector2(0f, 0f);
    18.  
    19. private void Move()
    20. {
    21.    Vector3 r = transform.right, f = transform.forward;
    22.     r.y = 0;
    23.     f.y = 0;
    24.     transform.position = transform.position + (r.normalized * prevInput.x + f.normalized * prevInput.y) * 2 * Time.deltaTime;
    25. }
    Here in awake we are creating new controls object and adding SetMove() and ResetMove() to performed and canceled events because those are raised only when some changes occur. So if you don't use those and were to hold your stick at a particular position you would not keep moving in that direction.

    So simply setting and resetting prevInput and updating the transform position according to prevInput.

    Similarly you can make a right stick and add a mapping to rotate the camera.

    And for On screen stick set control path to Left Stick [Gamepad]

    I learned about new input system a few days back here.
     
  3. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,394
    Setting up joysticks (or any device) with specific roles is possible and can be used inside the bindings for actions as well as with OnScreenControls.

    Any device has an arbitrary set of "usages" that can be applied to it. These are just string tags that can be applied dynamically at runtime using InputSystem.SetDeviceUsage or InputSystem.AddDeviceUsage.

    One way to exploit these usages is with the path strings. You can drop a binding into text mode with the little T button and then type stuff like "<Joystick>{Left}/trigger" (binds to the "trigger" control of the device of type Joystick which is tagged with the "Left" usage).

    However, a far more elegant way is to tell the system about the usages you intend to use. If you do this, this will show up in the control picker as well. You can apply this to any existing layout in the system through what's called a "layout override". Check out the "Custom Device Usages" sample for a working sample of this.

    Code (CSharp):
    1. // Let's say you want to have two joysticks. One tagged
    2. // with "Left" and one with "Right".
    3. InputSystem.RegisterLayoutOverride(@"
    4.    {
    5.        ""name"" : ""JoystickWithUsageTags"",
    6.        ""extend"" : ""Joystick"",
    7.        ""commonUsages"" : [
    8.            ""Left"", ""Right""
    9.        ]
    10.    }
    11. ");
    This override causes the settings you apply to directly write over the built-in Joystick layout. With this done (somewhere in the startup sequence), you will see the following in the control picker.

    upload_2020-3-27_18-38-24.png

    Now you can bind specifically to the left and the right joystick individually. This works in .inputactions files but also wherever else the control picker is used. I.e. also with OnScreenControls.

    Also, this allows setting up control schemes that specifically require a Left and a Right joystick, for example.

    There is one more step missing, though. At runtime, you need to actually assign the usages to joysticks for the bindings to become active.

    Code (CSharp):
    1. InputSystem.SetDeviceUsage(joystick1, "Left");
    2. InputSystem.SetDeviceUsage(joystick2, "Right");
    The way OnScreenControl works ATM, it will have an inherent one-frame lag. Something we should probably fix.

    ////EDIT: I just realized that OnScreenControls will not create the devices with these usages correctly. Looking at the code, I found an existing FIXME in there about this. ATM the code ignores usages in the paths and does not apply them to the devices. I'll have a look at that.
     
    Last edited: Mar 27, 2020
    Isaacg likes this.
  4. Isaacg

    Isaacg

    Joined:
    Nov 17, 2013
    Posts:
    9
    Yep, so the problem was that I was trying to match the virtual joystick with a Touchscreen/Position binding. There's nothing wrong with the On-ScreenStick script, if I bind it to a gamepad joystick it actually works!

    Thank you both!
     
  5. datagreed

    datagreed

    Joined:
    Sep 17, 2018
    Posts:
    23
    So how do I actually use OnScreenStick? Should I add an UI Image to a canvas and assign a script to it to actually see the joystick and use it?

    Is it possible to my scripts notified when user releases the stick completely (not just drags it to 0,0, but actually releases the thumb?)

    And how do the on-screen buttons work? How do I add them and add visual states pressed down/released?
     
  6. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,394
    @datagreed Recommend having a look at the OnScreenControls sample that comes with the package. Some doc improvements for these will land in 1.1.

    For OnScreenSticks, add an Image UI object and then add the OnScreenStick component to it. Set "Control Path" to a stick/Vector2 control on a device. Use the Image component to customize the appearance.

    For OnScreenButtons, add a Button UI object and then add the OnScreenButton component to it. Set "Control Path" to a button control on a device. Customize the button appearance as normal.

    The on-screen controls will create virtual devices. Every distinct type of device (such as "Gamepad") reference by the controls will create one instance of a device. If multiple controls reference "Gamepad", for example, only one Gamepad is created. Each on-screen control component feeds into the input control that it references through its path.

    Simply add a component to the stick that implements IPointerUpHandler. You get a call when the user lifts the finger off the screen after a stick interaction.
     
  7. datagreed

    datagreed

    Joined:
    Sep 17, 2018
    Posts:
    23
    @Rene-Damm thank you very much for so detailed answer! Will give it a try.

    > Recommend having a look at the OnScreenControls sample that comes with the package.

    Could you please tell me how do I fin this sample? Is it some kind of a demoscene or something else? I've installed the package via package manager, how do I find this sample?
     
  8. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,394
    See here.
     
  9. datagreed

    datagreed

    Joined:
    Sep 17, 2018
    Posts:
    23
    thanks!
     
unityunity