touch.position, Mathf.Abs... Please Help Me!!


I’m very new to this. I don’t know much about scripting, but I’m starting to wrap my head around it.

I’m having trouble with detecting a swipe. I’m not getting errors in my script, but it doesn’t seem to be calculating Mathf.Abs properly and therefore I’m not achieving the desired effect.

I narrowed it down and I believe that it is a problem with what touch.position is returning. This is what I’m doing:

If I want to get a vertical swipe I get the start touch.position and end touch.position and subtract the end position ( x ) from the start position ( x ) and see if it is less than a specific pixel value (200 pixels for example). If it is less than the pixel value, then it is considered to be a swipe. I do the same for horizontal swipes. (there are other conditions that have to be met in order for a swipe to be recognized, but this is the only problematic condition)

The problem is that the end touch.position is always returning a larger number for x than for y regardless of wether it is a vertical or horizontal swipe. My understanding is that touch.position returns the Vector 2 like this (x,y).

Is there anybody out there that can help??? Please provide an example for the ultra newb.

Here is my code:

#pragma strict

function Start () {

var touchedObj: boolean = false; // Has the object been touched

var moving: boolean = false; // this has to be true to move

var comfortZoneVerticalSwipe: float = 500; // the vertical swipe will have to be inside a 50 pixels horizontal boundary

var comfortZoneHorizontalSwipe: float = 50; // the horizontal swipe will have to be inside a 50 pixels vertical boundary

var minSwipeDistance: float = 14; // the swipe distance will have to be longer than this for it to be considered a swipe

var maxSwipeTime: float = 10; // the swipe time will have to be less than this to be considered a swipe

//the following 4 variables are used in some cases that I don’t want my character to be allowed to move on the board (it’s a board game)
var allowGoUp: boolean = true;
var allowGoRight: boolean = true;
var allowGoLeft: boolean = true;
var allowGoDown: boolean = true; 

function Update () 

	if (Input.touchCount >0) 
		var touch = Input.touches[0];

		switch (touch.phase) 
		{ //following are 2 cases
			case TouchPhase.Began: //here begins the 1st case
			var ray = Camera.main.ScreenPointToRay(touch.position);

			var hit : RaycastHit;
			var layerMask = 1 << 8;
			var startPos = touch.position;
			var startTime = Time.time;
			if (Physics.Raycast (ray, hit, Mathf.Infinity, layerMask))
				touchedObj = true;
			break; //here ends the 1st case
			case TouchPhase.Ended: //here begins the 2nd case
			Debug.Log (startPos);
			var swipeTime = Time.time - startTime;
			var swipeDist = (touch.position - startPos).magnitude;
			var endPos = touch.position;
			Debug.Log (endPos); //This is how I found that the x value in the end touch.position is always greater regardless of the horizontal or vertical swipe
			if (touchedObj && Mathf.Abs(touch.position.x - startPos.x)<comfortZoneVerticalSwipe && (swipeTime < maxSwipeTime) && (swipeDist > minSwipeDistance) && Mathf.Sign(touch.position.y - startPos.y)>0 && !moving && allowGoUp)
				//... then go up
				print ("UPUPUP");
				// code here for upward movement

			if (touchedObj && (Mathf.Abs(touch.position.x - startPos.x))<comfortZoneVerticalSwipe && (swipeTime < maxSwipeTime) && (swipeDist > minSwipeDistance) && Mathf.Sign(touch.position.y - startPos.y)<0 && !moving && allowGoDown)
				//... then go down
				print ("DOWNDOWN");
				// code here for downward movement

			if (touchedObj && (Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe && (swipeTime < maxSwipeTime) && (swipeDist > minSwipeDistance) && Mathf.Sign(touch.position.x - startPos.x)<0 && !moving && allowGoLeft)
				//... then go left
				print ("LEFTLEFT");
				// code here for left movement

			if (touchedObj && (Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe && (swipeTime < maxSwipeTime) && (swipeDist > minSwipeDistance) && Mathf.Sign(touch.position.x - startPos.x)>0 && !moving && allowGoRight)
				//...then go right
				print ("RIGHTRIGHT");
				// code here for right movement

			break;	 //here ends the 2nd case


Keep in mind that I’m using “Unity Remote 3” to test this on my iPad.

I was thinking that a raycast might work, but I would think that it isn’t necessary since touch.position should do the job fine. If you think a raycast is the only way to do this, could you please supply an example.

Thanks a mil in advance.

I took a look at your code above on the iPad (i.e. not using Unity Remote). There are a few problems. The one that is likely causing you issues is that ‘startPos’ is a local variable to Update(), so it loses it value between the time Update is call for your TouchPhase.Began case and for the TouchPhase.Ended case. You need to move it out of the Update() function.

More minor issues are that touchedObj is never reset to false, so after a first swipe on the object, all other swipes will be passed on even if the swipe does not touch the object. Another small issue is that you are using screen/pixel calculations for some of your checks (how big (i.e. as a percentage of the screen) the swipe is will heavily depend on the resolution of the device).

On the actual device the pixel coordinates returned by touch.position were correct…the x value wasn’t always larger than the y value, and the values seem correct with respect to the coordinates of the screen (i.e. 0,0 in the upper left corner).

I second @VicM 's suggestion to take a look at something to abstract away touch code. We use FingerGestures.