Pinch, and other multi-finger gestures, in modern Unity3D?
<p>In modern Unity3D, we use the IPointerDownHandler family of calls.</p>
<p>Regarding the <code>IPointerDownHandler</code> family of calls,</p>
<pre><code>public class FingerMove:MonoBehaviour, IPointerDownHandler...
    {
    public void OnPointerDown (PointerEventData data)
        {
</code></pre>
<p>Of course they are fantastic</p>
<h1>for dealing with single touches.</h1>
<p>But how do you deal with <strong>multiple touches</strong> in a serious way?</p>
<p>You can &quot;do it all by hand&quot; tracking the touches yourself, but it seems incredible Unity would want you to do that for something so absolutely basic. (I mean - it's a game engine. Sure, I could also write all my own rendering and physics!)</p>
<p>Here's an example of basically &quot;cowboy programming&quot;, just doing it by hand with no software engineering.  What's the real solution?</p>
<pre><code>//
// example of programming a pinch (as well as swipes) using modern Unity
//
// here we are forced to track &quot;by hand&quot; in your own code
// how many fingers are down and which 
// fingers belong to you etc etc:
//

// pedagogic example code:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;

public class FingerMove:MonoBehaviour,
         IPointerDownHandler, IDragHandler, IPointerUpHandler
    {
    // these three for the ordinary one-finger-only drag
    private Vector2 prevPoint;
    private Vector2 newPoint;
    private Vector2 screenTravel;
    // and this one is the ordinary one-finger-only drag
    private int currentMainFinger = -1;
    
    // and this for the (strictly second finger only) drag...
    private int currentSecondFinger = -1;
    private Vector2 posA;
    private Vector2 posB;
    
    private float previousDistance = -1f;
    private float distance;
    private float pinchDelta = 0f;
    
    public void OnPointerDown (PointerEventData data)
        {
        if (currentMainFinger == -1)
            {
            // this is the NEW currentMainFinger
            currentMainFinger = data.pointerId;
            prevPoint = data.position;
            
            // and for the drag (if it becomes used)...
            posA = data.position;
            
            return;
            }
        
        if (currentSecondFinger == -1)
            {
            // this is the NEW currentSecondFinger
            currentSecondFinger = data.pointerId;
            posB = data.position;
            
            figureDelta();
            previousDistance = distance;
            
            return;
            }
        
        Debug.Log(&quot;third+ finger! (ignore)&quot;);
        }

    public void OnDrag (PointerEventData data)
        {
        // handle single-finger moves (swipes, drawing etc) only:
        
        if ( currentMainFinger == data.pointerId )
            {
            newPoint = data.position;
            screenTravel = newPoint - prevPoint;
            prevPoint = newPoint;
            
            if (currentSecondFinger == -1)
                {
                Debug.Log(&quot;NO 2f&quot;);
                _processSwipe(); // handle it your way
                }
            else
                {
                }
            
            // and for two-finger if it becomes used next frame
            // or is already being used...
            posA = data.position;
            }
        
        if (currentSecondFinger == -1) return;
        
        // handle two-finger (eg, pinch, rotate etc)...
        
        if ( currentMainFinger == data.pointerId ) posA = data.position;
        if ( currentSecondFinger == data.pointerId ) posB = data.position;
        
        figureDelta();
        pinchDelta =  distance - previousDistance;
        previousDistance = distance;
        
        _processPinch(); // handle it your way
        }
    
    private void figureDelta()
        {
        // when/if two touches, keep track of the distance between them
        distance = Vector2.Distance(posA, posB);
        }
    
    public void OnPointerUp (PointerEventData data)
        {
        if ( currentMainFinger == data.pointerId )
            {
            currentMainFinger = -1;
            }
        if ( currentSecondFinger == data.pointerId )
            {
            currentSecondFinger = -1;
            }
        }
    
    private float sensitivity = 0.3f;
    
    // in this example, the swipes/pinch affects these three calls:
    public Changer orbitLR;
    public Changer orbitUD;
    public Changer distanceZ;
    // initial values of those...
    private float LR = -20f;
    private float UD = 20f;
    private float distanceCam = 5f;
    
    private void _processSwipe()
        {
        // in this example, just left-right or up-down swipes
        
        LR = LR + sensitivity * screenTravel.x;
        UD = UD - sensitivity * screenTravel.y;
        
        LR = Mathf.Clamp(LR, -150f, 30f);
        UD = Mathf.Clamp(UD, 5f, 50f);
        
        orbitLR.RotationY = LR;
        orbitUD.RotationX = UD;
        }
    
    private void _processPinch()
        {
        // in this example, pinch to zoom
        
        distanceCam = distanceCam - pinchDelta * 0.0125f;
        distanceCam = Mathf.Clamp(distanceCam, 3f, 8f);
        distanceZ.DistanceZ = distanceCam;
        }
    
    }
</code></pre>
<p>(Note, please do not answer regarding the legacy &quot;Touches&quot; system which is unusable. This about normal modern Unity development.)</p>