Search Unity

Resolved How to block primary touch/delta with UI?

Discussion in 'Input System' started by Arycama, Nov 2, 2020.

  1. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    I'm working on a simple mobile input system, with a virtual joystick for movement.

    I want to use touch-delta to control camera rotation, but only when the virtual joystick is not being pressed.

    However, using the included on screen control examples, this is not the case. The left joystick will move the player, but it will not stop the Primary Touch/Delta [Touchscreen] from also being detected which causes the camera to rotate while trying to use the joystick for movement.

    Surely this is a very common use case, is there a simple way to handle it through the new input system? I'm testing in Editor with the included "Player Input" and "Touch Simulation" components.
     
  2. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    I figured out a solution, leaving this here incase anyone else runs into the same issue.

    I created my own OnScreenControl, using input delta instead of a virtual joystick position. This way it can be fed to whatever input you like (Eg right stick) and work with the system as usual.

    It will be blocked by any UI in front of it, as expected. So it can be blocked by a virtual joystick or other UI input. I've yet to test it on device, but it works in Editor and build with the TouchSimulation component in the scene somewhere.

    To use, just add this to a UI Graphic, (Eg an image with zero alpha, but ensure you tick "Cull Transparent Mesh" on the CanvasRenderer to avoid overdraw) and set the control path through the inspector.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.InputSystem.Layouts;
    4. using UnityEngine.InputSystem.OnScreen;
    5.  
    6. public class OnScreenMouse : OnScreenControl, IDragHandler
    7. {
    8.     [SerializeField, InputControl(layout = "Vector2")]
    9.     private string m_ControlPath;
    10.  
    11.     private bool hasDrag;
    12.     private Vector2 delta;
    13.  
    14.     protected override string controlPathInternal { get => m_ControlPath; set => m_ControlPath = value; }
    15.  
    16.     private void LateUpdate()
    17.     {
    18.         if(hasDrag)
    19.         {
    20.             SendValueToControl(delta);
    21.             hasDrag = false;
    22.         }
    23.         else
    24.         {
    25.             SendValueToControl(new Vector2(0, 0));
    26.         }
    27.     }
    28.  
    29.     void IDragHandler.OnDrag(PointerEventData eventData)
    30.     {
    31.         delta = eventData.delta;
    32.         hasDrag = true;
    33.     }
    34. }
    35.  
     
    Last edited: Nov 2, 2020
  3. oOtroyOo

    oOtroyOo

    Joined:
    Jun 7, 2015
    Posts:
    4
    Thanks for this . I just don't understand why then diden't put this funcion in examples.
     
    Resonantmango likes this.
  4. Razeen_AG

    Razeen_AG

    Joined:
    Aug 5, 2019
    Posts:
    3
    I tried this but it didnt work, it is not updating hasDrag foe some reason

    it works fine on PC but not on device
     
  5. Nivikantavo

    Nivikantavo

    Joined:
    Sep 22, 2020
    Posts:
    2
    Hi, I ran into the same problem, tried to use your solution, but when running on the phone, the usual OnScreenControl continues to work and data is read as if from two touch screens, maybe someone has already solved this problem?