two finger swipe vs pinch and zoom problem

I have a problem with code for a camera scene for android. I can pan my camera fine, but once i use two fingers my code confuses a pinch with a two finger swipe. I want to zoom when i pinch, and rotate when i swipe with two fingers, but it always does both if i try to swipe.

I figured if i could draw a line between both points using their coordinates and then translate that line to the left and right of both points (or if points or horizontal to translate it below and above the points) and then check if either finger goes out of these two lines and if it does cancel that swipe possibility.

alt text

The red circles are the touch locations, while the blue lines are the lines drawn to represent the limits of each finger…

How would i do this? i know i can calculate a line using this:
but how would i check the coords against this line?

I’m assuming i would create this line at the begin touch phase, and then check it until the touch cancelled phase. How would i go about doing this?

How would i also take into account if the lines are horizontal or vertical?
Finger pinches can be horizontal or vertical.

It gives me much more pleasure answering this question than your other one, so I can understand why you wanted to answer it yourself so many times. But please, constrain all your enthusiasm into 1 answer only. You can even move some of them as comments into the respective answers you were referring to and simply deleting the repetitive answer claims. Also sorry for insisting so much on keeping it clean.

Anyways, following there are simplified illustrative comment-stripped script for you and the full copy of it under unifycommunity. Right now I can’t test it on any device and just want to say for panning I did a lot more of fixes not included here that I hope are only needed on my end for any reason.


still building it - sorry - this is where the panning part is, which envolves no Touch controls as you may deduce


using UnityEngine;
using System.Collections;

public class DetectTouchMovement : MonoBehaviour {
	const float pinchTurnRatio = Mathf.PI / 2;
	const float minTurnAngle = 0;
	const float pinchRatio = 1;
	const float minPinchDistance = 0;
	const float panRatio = 1;
	const float minPanDistance = 0;
	static public float turnAngleDelta;
	static public float turnAngle;

	static public float pinchDistanceDelta;
	static public float pinchDistance;
	static public void Calculate () {
		pinchDistance = pinchDistanceDelta = 0;
		turnAngle = turnAngleDelta = 0;
		// if two fingers are touching the screen at the same time ...
		if (Input.touchCount == 2) {
			Touch touch1 = Input.touches[0];
			Touch touch2 = Input.touches[1];
			// ... if at least one of them moved ...
			if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved) {
				// ... check the delta distance between them ...
				pinchDistance = Vector2.Distance(touch1.position, touch2.position);
				float prevDistance = Vector2.Distance(touch1.position - touch1.deltaPosition,
				                                      touch2.position - touch2.deltaPosition);
				pinchDistanceDelta = pinchDistance - prevDistance;
				// ... if it's greater than a minimum threshold, it's a pinch!
				if (Mathf.Abs(pinchDistanceDelta) > minPinchDistance) {
					pinchDistanceDelta *= pinchRatio;
				} else {
					pinchDistance = pinchDistanceDelta = 0;
				// ... or check the delta angle between them ...
				turnAngle = Angle(touch1.position, touch2.position);
				float prevTurn = Angle(touch1.position - touch1.deltaPosition,
				                       touch2.position - touch2.deltaPosition);
				turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);
				// ... if it's greater than a minimum threshold, it's a turn!
				if (Mathf.Abs(turnAngleDelta) > minTurnAngle) {
					turnAngleDelta *= pinchTurnRatio;
				} else {
					turnAngle = turnAngleDelta = 0;
	static private float Angle (Vector2 pos1, Vector2 pos2) {
		Vector2 from = pos2 - pos1;
		Vector2 to = new Vector2(1, 0);
		float result = Vector2.Angle( from, to );
		Vector3 cross = Vector3.Cross( from, to );
		if (cross.z > 0) {
			result = 360f - result;
		return result;

What I did was detect when there are two touches, and track the distance between them. If the distance decreases, it’s a zoom-out; if it increases, it’s a zoom in. At the same time, I find the center between the two touches, that’s the center of rotation. There’s also a small threshold value that has to be exceeded before the action takes place. It’s up to the user not to move their fingers apart or together while rotating, and that threshold helps keep them in line, so to speak.

Would it be possible to simply check if both fingers are moving in the same direction?

If so, you could ignore pinch/zoom input when this is the case.

Unless a pinch is moving perfectly along one of the axes, the two fingers should be moving in the opposite direction both horizontally and vertically, right?

(I guess the answer to this question depends on how you define pinch/zoom)

Hmm, what stops me from using two fingers and swiping left in the pinch/zoom code? It still tries to zoom out if i use two fingers and swipe left (and assuming up, down and right too). How would i stop this and determine the best way to overcome this error?

Any people have any ideas on this? I still cannot discern how to check that two fingers are performing a pinch without zooming if i swipe them vertically, horizontally or diagonally… I want to do this and still be able to zoom if they perform the pinch while swiping… (it would combo with a rotate action i have set for swiping two fingers)

How would i do this? What values does the .position data member actually contain? Is it a vector 2? Does .deltaPosition of a touch position ever become negative??