Pinch and Scroll with Unity’s New Input System

Learn how to build a simple input system to detect pinches on touch screens and scroll wheel turns with the mouse using the new Unity Input System and Unity Events. This approach uses bindings with modifiers to detect if two fingers are touching the screen and gets the position values through the enhanced touch API. 

The Player Input Action Map

We want to define our player input actions in the player input action map. 

We first want an action with “Action Type” = “Value” and “Control Type” = “Vector2” and we can name this something like “Pinch [Touch]”. Then, “Add Binding With Two Modifiers” and set the first Modifier to “Touch#0/Touch Contact?” and the second modifier to “Touch#1/Touch Contact?”. This will check if both finger 0 (primary finger) and finger 1 (secondary finger) are on the screen. Then, as the binding add a continuous value stream, such as “Delta [Touchscreen]”. 

For the scroll wheel interaction, add a new action and call it something sensible like “Scroll [Mouse]” with an “Action Type” = “Value” and “Control Type” = “Vector2”. Then simply add a Binding to “Scroll [Mouse]”.

The Player Input Controller

Probably why 99% of you are here, for your convinience, the code 🙂 Let me know if you have any ideas on how to improve this script and if this helped you in any way, subscribe and leave a like on Youtube. 

				
					using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.EnhancedTouch;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
using TouchPhase = UnityEngine.InputSystem.TouchPhase;

public class PlayerInputController : MonoBehaviour
{
    public Transform sphereTransform;

    private void Awake()
    {
        // Enable enhanced touch support if not already
        if (!EnhancedTouchSupport.enabled)
            EnhancedTouchSupport.Enable();
    }

    public void Pinch(InputAction.CallbackContext context)
    {
      
        // if there are not two active touches, return
        if (Touch.activeTouches.Count < 2)
            return;
        
        // get the finger inputs
        Touch primary = Touch.activeTouches[0];
        Touch secondary = Touch.activeTouches[1];

        // check if none of the fingers moved, return
        if (primary.phase == TouchPhase.Moved || secondary.phase == TouchPhase.Moved)
        {
            // if fingers have no history, then return
            if (primary.history.Count < 1 || secondary.history.Count < 1)
                return;
                
            // calculate distance before and after touch movement
            float currentDistance = Vector2.Distance(primary.screenPosition, secondary.screenPosition);
            float previousDistance = Vector2.Distance(primary.history[0].screenPosition, secondary.history[0].screenPosition);
                
            // the zoom distance is the difference between the previous distance and the current distance
            float pinchDistance = currentDistance - previousDistance;
            Zoom(pinchDistance);
        }
    }

    public void Scroll(InputAction.CallbackContext context)
    {
                    
        if (context.phase != InputActionPhase.Performed)
            return;

        float scrollDistance = context.ReadValue<Vector2>().y;
        Zoom(scrollDistance);
    }

    public void Zoom(float distance)
    {
        distance = distance * 0.01f;
        sphereTransform.localScale += new Vector3(distance, distance, distance);
    }
    
}