I have looked and looked for examples and it would be great if someone would be able to just make a small script to show how to do this. I would like to know how to detect swipes, left right up and down if possible. I have noticed people seem reluctant to show any code (I have no idea why) and the scripts I can find are a bit over the top it seems.
*sigh* Why is the JS source of swipe code so elusive? We are developing for iPhone are we not? Can anyone from Unity help. I appreciate the C# versions, but no idea how to implement them into my app that is all JS (and all that I know in limited programming skills). Swipe left > do something Swipe right > do something Thats all i need to figure out. The only thing I've found in JS so far that works is this (sorry can't find the Unity forum link for it to credit it: Code (csharp): var smoothingConstant = .01; // Speed of ending-swipe //private var layerMask = 1 << 11; // Only check for collisions in TouchManager layer private var hit : RaycastHit; // Hit variable private var joystickId : int; // Stores which finger is on the joystick private var previousTouch : iPhoneTouch; // Stores the previous touch private var endedTouch = false; // Informs when the touch has ended private var velocity : float; // Velocity private var time : float; // Time private var acceleration : float; // Acceleration var test : GameObject; function Update () { for (var touch : iPhoneTouch in iPhoneInput.touches) { // Draw a ray from the camera to the touch position var ray : Ray = Camera.main.ScreenPointToRay (touch.position); // If the touch is new, and it is on the joystick, then store the touch in joystickId if (touch.phase == iPhoneTouchPhase.Began touch.position.x < 150) { joystickId = touch.fingerId; } // If the finger is not on the joystick, check to see if it hits the "able to swipe" area. If so, then call the swipe function // Note -- the collision is a box, with rendering removed in layer 11. It is the child of the parent, and is the appropriate size. if (touch.phase != iPhoneTouchPhase.Ended touch.phase == iPhoneTouchPhase.Moved) { // if (Physics.Raycast (ray, hit, layerMask)) { if (endedTouch) previousTouch = touch; Swipe(touch); previousTouch = touch; endedTouch = false; Instantiate(test); } // If the finger doing the swipe has been removed, then reset all the variables else if (touch.phase == iPhoneTouchPhase.Ended) { endedTouch = true; velocity = 0; time = 0; } // If the touch ended, smooth it out if (endedTouch == true) { if ( velocity != 0) SmoothEnding(); } } } // Swipe function function Swipe ( touch : iPhoneTouch ) { // Temporary variables var deltaTouch : float = (touch.position.x - previousTouch.position.x); var initialTime = time; var initialVelocity = deltaTouch/(time); // Stored variables time += Time.deltaTime; velocity = deltaTouch/(time); acceleration = (velocity - initialVelocity)/(time - initialTime); // Transform the position with respect to acceleration //transform.Rotate(0, -deltaTouch * Time.deltaTime, 0); transform.Rotate(0, velocity * Time.deltaTime, 0); Debug.Log("Acceleration =" + acceleration + " and Velocity = " + velocity); } HOWEVER, I can't for the life of me figure out how to change/add to this code to detect swipe direction. Any help greatly appreciated... I've been hogging these forums tonight with this issue hoping to find some assistance somewhere!
The basic routine is:- - On the touch start phase, record the position and the time and set a boolean value to say that a swipe might be happening. - Each frame during the drag phase, check that the finger doesn't stray too far from a straight line (horizontal or vertical, depending on the swipe type). If it does stray, cancel the boolean flag to denote it isn't a swipe. - On the end phase, again, record the time and position and subtract the initial time and position. If the time is greater than the maximum swipe time or the distance is less than the minimum swipe distance, or the boolean flag is false then it's not a swipe. Otherwise, it is. Annoyingly, I can't test the following code on a device at the moment, but it should at least give you an idea. This is for a vertical swipe, but you can get a horizontal swipe by changing touch.position.y for touch.position.x, etc. Code (csharp): var startTime: float; var startPos: Vector2; var couldBeSwipe: boolean; var comfortZone: float; var minSwipeDist: float; var maxSwipeTime: float; function Update() { if (iPhoneInput.touchCount > 0) { var touch = iPhoneInput.touches[0]; switch (touch.phase) { case iPhoneTouchPhase.Began: couldBeSwipe = true; startPos = touch.position; startTime = Time.time; break; case iPhoneTouchPhase.Moved: if (Mathf.Abs(touch.position.y - startPos.y) > comfortZone) { couldBeSwipe = false; } break; case iPhoneTouchPhase.Stationary: couldBeSwipe = false; break; case iPhoneTouchPhase.Ended: var swipeTime = Time.time - startTime; var swipeDist = (touch.position - startPos).magnitude; if (couldBeSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDist)) { // It's a swiiiiiiiiiiiipe! var swipeDirection = Mathf.Sign(touch.position.y - startPos.y); // Do something here in reaction to the swipe. } break; } } }
Thanks for this. This script looks a lot cleaner than the one I've 'hacked' together to get things working. I'll take a look.... Thanks for your help
So this swipe detection is great, but how do I move an object based upon the distance and direction of the swipe? I need to move a camera (in any direction, its a top down 2d game) based upon the length and direction of the swipe. Then it should slow down, then stop moving. The camera should also move while the finger is dragging. Any thoughts?
Not exactly what you're trying to do but might get you started in that direction: http://forum.unity3d.com/viewtopic.php?t=16159
SWIPE WITH TOUCH........THIS REALLY WORKS.......... TRY IT /////////////////////////////////////////////// code:- ///////////////////////////////////////////// using UnityEngine; using System.Collections; public class Touch { public iPhoneTouch touch1; public Vector2 Start_pos; public float time1; } public class swipe : MonoBehaviour { ArrayList ar=new ArrayList(); float x_dir,y_dir; // Use this for initialization void Start () { } Vector2 end_pos,start_pos; GameObject txt; TextMesh tm; // Update is called once per frame void Update () { txt=GameObject.Find("New Text"); //tm=txt.GetComponent(typeof(TextMesh)) as TextMesh; //txt.transform.position=pos; GameObject c=GameObject.Find("Cube"); foreach(iPhoneTouch touch in iPhoneInput.touches) { if(touch.phase==iPhoneTouchPhase.Began) { Vector2 temp=camera.WorldToScreenPoint(c.transform.position); Vector2 t=touch.position; if(temp.x+25>t.x temp.x-25<t.x) { if(temp.y+25>t.y temp.y-25<t.y ) { Touch ob =new Touch(); ob.time1=(float)Time.time; ob.touch1=touch; ob.Start_pos=t; ar.Add(ob); } } } if(touch.phase==iPhoneTouchPhase.Ended) { for(int i=0;i<ar.Count;i++) { Touch ob=(Touch)ar; if(ob.touch1.fingerId==touch.fingerId) { float time_end=(float)Time.time; if((time_end-ob.time1)<1) { end_pos=touch.position; /*if(end_pos.x>ob.Start_pos.x) { x_dir=(end_pos.x-(end_pos.x-ob.Start_pos.x)); } else { x_dir=ob.Start_pos.x-(ob.Start_pos.x-end_pos.x); } if(end_pos.y>ob.Start_pos.y) { y_dir=end_pos.y-(end_pos.y-ob.Start_pos.y); } else { y_dir=ob.Start_pos.y-(ob.Start_pos.y-end_pos.y); }*/ // float dir=Mathf.Atan2((end_pos.y-ob.Start_pos.y),(end_pos.x-ob.Start_pos.x)); c.rigidbody.AddForce((end_pos.x-ob.Start_pos.x)*10,(end_pos.y-ob.Start_pos.y)*10,0); //tm.text=iPhoneInput.touchCount); ar.RemoveAt(i); }} } } } } // //void t1(iPhoneTouch t2) // //{ // //if(t2.phase==iPhoneTouchPhase.) //{ // // // // // } // // } }
////////////////////////////////// SWIPE WITH TOUCH ////////////////////////////////// using UnityEngine; using System.Collections; public class Touch { public iPhoneTouch touch1; public Vector2 Start_pos; public float time1; } public class swipe : MonoBehaviour { ArrayList ar=new ArrayList(); float x_dir,y_dir; // Use this for initialization void Start () { } Vector2 end_pos,start_pos; GameObject txt; TextMesh tm; // Update is called once per frame void Update () { txt=GameObject.Find("New Text"); //tm=txt.GetComponent(typeof(TextMesh)) as TextMesh; //txt.transform.position=pos; GameObject c=GameObject.Find("Cube"); foreach(iPhoneTouch touch in iPhoneInput.touches) { if(touch.phase==iPhoneTouchPhase.Began) { Vector2 temp=camera.WorldToScreenPoint(c.transform.position); Vector2 t=touch.position; if(temp.x+25>t.x temp.x-25<t.x) { if(temp.y+25>t.y temp.y-25<t.y ) { Touch ob =new Touch(); ob.time1=(float)Time.time; ob.touch1=touch; ob.Start_pos=t; ar.Add(ob); } } } if(touch.phase==iPhoneTouchPhase.Ended) { for(int i=0;i<ar.Count;i++) { Touch ob=(Touch)ar; if(ob.touch1.fingerId==touch.fingerId) { float time_end=(float)Time.time; if((time_end-ob.time1)<1) { end_pos=touch.position; /*if(end_pos.x>ob.Start_pos.x) { x_dir=(end_pos.x-(end_pos.x-ob.Start_pos.x)); } else { x_dir=ob.Start_pos.x-(ob.Start_pos.x-end_pos.x); } if(end_pos.y>ob.Start_pos.y) { y_dir=end_pos.y-(end_pos.y-ob.Start_pos.y); } else { y_dir=ob.Start_pos.y-(ob.Start_pos.y-end_pos.y); }*/ // float dir=Mathf.Atan2((end_pos.y-ob.Start_pos.y),(end_pos.x-ob.Start_pos.x)); c.rigidbody.AddForce((end_pos.x-ob.Start_pos.x)*10,(end_pos.y-ob.Start_pos.y)*10,0); //tm.text=iPhoneInput.touchCount); ar.RemoveAt(i); }} } } } } // //void t1(iPhoneTouch t2) // //{ // //if(t2.phase==iPhoneTouchPhase.) //{ // // // // // } // // } }
I recently posted a working example on my blog of getting a UnityGUI list to scroll up and down in response to swipes. I walk through it a piece at a time, so I am hopeful that someone interested in handling swipes in general could learn from it. The code is in C#, but it should be easy to port, the code is mostly if-then statements, numeric assignments, and comparisons. http://www.mindthecube.com/blog/2010/09/adding-iphone-touches-to-unitygui-scrollview
Thanks for the easily understandable code andeeee. I applied the code on a game object and that's supposed to make an iTween movement as a reaction to the swipe. I get the following error though: Assets/scripts/SwipeScript.js (14,36): BCE0020: An instance of type 'UnityEngine.Touch' is required to access non static member 'phase'. What does this mean? :-/
ok I'd made a typo at the referred line and that caused the error - I apologise... Just one thing: what values for comfortZone and minSwipeDist (in andeeee's script) would you recommend? Also: shouldn't the if condition in line 21, check to see if (touch.position.x - startPos.x) > comfortZone) for a vertical swipe? I tried a large range of values (beginning from the obvious - I think - around 50 to100) but I get to achieve a swipe veeery difficult (I set the maxSwipeTime to a very large value to make sure my swipe speed is not the problem). That's strange.
(Regarding andeeee's script) I modified the script in a way that I avoid everything that has to do with the couldBeSwipe: boolean and strangely enough it works great. Thanks so much andeeee, I was searching and searching and the script you suggested (with a few tiny modifications) did my job perfectly!!!
prangya_p and kapilundan, I'm really sorry for not having responded for so long, I hadn't visited the thread and I wasn't notified that there were replies to it (maybe I could change this from my settings), I guess my answer is not so useful after 50 days but I'm posting it anyway as it could be useful to others at least... I use the following script, that is attached to my character (something like a chess pawn) and will move it on a board horizontally or vertically, depending on the swipes. The swipes can be made anywhere on the screen and you don't have to make them on the character. var comfortZoneVerticalSwipe: float = 50; // 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 //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 startPos = touch.position; startTime = Time.time; break; //here ends the 1st case case TouchPhase.Ended: //here begins the 2nd case var swipeTime = Time.time - startTime; var swipeDist = (touch.position - startPos).magnitude; var endPos = touch.position; if ((Mathf.Abs(touch.position.x - startPos.x))<comfortZoneVerticalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.y - startPos.y)>0 !moving transform.position.z<3 allowGoUp) { //... then go up moving=true; [code here, to make character move the way you want (upwards)] } if ((Mathf.Abs(touch.position.x - startPos.x))<comfortZoneVerticalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.y - startPos.y)<0 !moving transform.position.z>-3 allowGoDown) { //... then go down moving=true; [code here, to make character move the way you want (downwards)] } if ((Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.x - startPos.x)<0 !moving transform.position.x>-2 allowGoLeft) { //... then go left moving=true; [code here, to make character move the way you want (to the left)] } if ((Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.x - startPos.x)>0 !moving transform.position.x<2 allowGoRight) { //...then go right moving=true; [code here, to make character move the way you want (to the right)] } break; //here ends the 2nd case } }
Hey Everyone, I thought I'd post this in case anyone was looking for a C# version of a swipe script. I converted Andee's into it and made a few modifications: 1) IPhoneTouch class is deprecated, so I converted it to use Input.Touches (I think someone did this earlier in javascript) 2) When determining the swipe distance, for strict vertical swipes I wanted it to only take the Y values into consideration. 3) The comfort zone comparison should be with touch.position.x not touch.position.y, so I fixed that. 4) I created an enumeration for the swipe direction. The direction, along with the swipe time are exposed as public variables, lastSwipe and lastSwipeTime respectfully. You can toss this script on an empty game object and access those values from other scripts to determine vertical swipes. 5) I also put in some debug messages to assist with fine tuning the comfort zone. It should be pretty easy to modify for horizontal swipes too. Since I have to do that, I will probably post that soon as well. Code (csharp): using UnityEngine; using System.Collections; public class SwipeDetector : MonoBehaviour { // Values to set: public float comfortZone = 70.0f; public float minSwipeDist = 14.0f; public float maxSwipeTime = 0.5f; private float startTime; private Vector2 startPos; private bool couldBeSwipe; public enum SwipeDirection { None, Up, Down } public SwipeDirection lastSwipe = SwipeDetector.SwipeDirection.None; public float lastSwipeTime; void Update() { if (Input.touchCount > 0) { Touch touch = Input.touches[0]; switch (touch.phase) { case TouchPhase.Began: lastSwipe = SwipeDetector.SwipeDirection.None; lastSwipeTime = 0; couldBeSwipe = true; startPos = touch.position; startTime = Time.time; break; case TouchPhase.Moved: if (Mathf.Abs(touch.position.x - startPos.x) > comfortZone) { Debug.Log("Not a swipe. Swipe strayed " + (int)Mathf.Abs(touch.position.x - startPos.x) + "px which is " + (int)(Mathf.Abs(touch.position.x - startPos.x) - comfortZone) + "px outside the comfort zone."); couldBeSwipe = false; } break; case TouchPhase.Ended: if (couldBeSwipe) { float swipeTime = Time.time - startTime; float swipeDist = (new Vector3(0, touch.position.y, 0) - new Vector3(0, startPos.y, 0)).magnitude; if ((swipeTime < maxSwipeTime) (swipeDist > minSwipeDist)) { // It's a swiiiiiiiiiiiipe! float swipeValue = Mathf.Sign(touch.position.y - startPos.y); // If the swipe direction is positive, it was an upward swipe. // If the swipe direction is negative, it was a downward swipe. if (swipeValue > 0) lastSwipe = SwipeDetector.SwipeDirection.Up; else if (swipeValue < 0) lastSwipe = SwipeDetector.SwipeDirection.Down; // Set the time the last swipe occured, useful for other scripts to check: lastSwipeTime = Time.time; Debug.Log("Found a swipe! Direction: " + lastSwipe); } } break; } } } }
Hummm, I also need a swipe in Unity. How about an implementation of iOS native UIGestureRecognizer with the following subclasses: UITapGestureRecognizer [Pinch, Rotation, Swipe, Pan, LongPress]? I haven't looked yet, but I gather it's not in Unity, right?
I haven't used it yet, but I believe Prime31's UIToolkit has components for swipe detection: http://forum.unity3d.com/threads/87...on-GUI-Solution-Ready-for-Use...and-it-s-free
This is the C# code i am using Thanks for sharing yours i was able to get mine going too Code (csharp): public float comfortZoneVerticalSwipe = 50; // the vertical swipe will have to be inside a 50 pixels horizontal boundary public float comfortZoneHorizontalSwipe = 50; // the horizontal swipe will have to be inside a 50 pixels vertical boundary public float minSwipeDistance = 14; // the swipe distance will have to be longer than this for it 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) public float startTime; public Vector2 startPos; public float maxSwipeTime; void Update(){ if (Input.touchCount >0) { Touch touch = Input.touches[0]; switch (touch.phase) { //following are 2 cases case TouchPhase.Began: //here begins the 1st case startPos = touch.position; startTime = Time.time; break; //here ends the 1st case case TouchPhase.Ended: //here begins the 2nd case float swipeTime = Time.time - startTime; float swipeDist = (touch.position - startPos).magnitude; if ((Mathf.Abs(touch.position.x - startPos.x))<comfortZoneVerticalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.y - startPos.y)>0) { if(playerY > 0 ) { playerY --; player.transform.position = LevelCreator.gridPositionArray[playerX,playerY]; CheckMine(); } print("up"); } if ((Mathf.Abs(touch.position.x - startPos.x))<comfortZoneVerticalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.y - startPos.y)<0) { if(playerY < LevelCreator.gridHeight -1) { playerY ++; player.transform.position = LevelCreator.gridPositionArray[playerX,playerY]; CheckMine(); } print("down"); } if ((Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.x - startPos.x)<0) { if(playerX > 0) { playerX --; player.transform.position = LevelCreator.gridPositionArray[playerX,playerY]; CheckMine(); } print("left"); } if ((Mathf.Abs(touch.position.y - startPos.y))<comfortZoneHorizontalSwipe (swipeTime < maxSwipeTime) (swipeDist > minSwipeDistance) Mathf.Sign(touch.position.x - startPos.x)>0) { if(playerX < LevelCreator.gridWidth -1) { playerX ++; player.transform.position = LevelCreator.gridPositionArray[playerX,playerY]; CheckMine(); } print("right"); } break; //here ends the 2nd case } } }
Hello All, I am still in the new stages of Unity but I am having soo much trouble with getting touch going on. So I used this code and attached it to my Character (who is a stationary character). I then proceed to build it to my Virtual Andriod phone, everything seems good but It doesn't seem to detect my touch! Any code I've used soo far has been this problem, is there any way to start testing me touch code? I haven't been able to write any yet because I am not sure if my virtual phone is even taking it ok... I'm sure this code works, but how will I know what it'll do once I put it on my phone? Unless there is another way to do touch detecting on the editor rather than on a virtual device? Please let me know if you. Thanks!
Hi, I want to play animations (left,right,up,down) on swipe ,that i did in Maya software .but i am not able to play , i really appreciate if anyone can help me. please find the below script. Im new to scripting , please tell me what am i doing wrong. using UnityEngine; using System.Collections; using UnityEngine.UI; public class PlayerControllerScript : MonoBehaviour { publicfloat speed =1;// speed in meters per second publicfloat smooth =2.0F; privateVector2 fp;// first finger position privateVector2 lp;// last finger position privatefloat horizontalMovement; privatefloat verticalMovement; voidStart() { animation.Play("idle"); } // Update is called once per frame voidUpdate(){ Vector3 moveDir =Vector3.zero; foreach(Touch touch inInput.touches) { if(touch.phase ==TouchPhase.Began) { fp = touch.position; lp = touch.position; } if(touch.phase ==TouchPhase.Moved) { lp = touch.position; if((fp.x - lp.x)>80)// left swipe { animation.Play("left"); } elseif((fp.x - lp.x)<-80)// right swipe { animation.Play("right"); } elseif((fp.y - lp.y)<-80)// up swipe { animation.Play("up"); } elseif((fp.y - lp.y)>80)// down swipe { animation.Play("down"); } } if(touch.phase ==TouchPhase.Ended) { verticalMovement =0; horizontalMovement =0; } } float tiltAroundY =0; if(!isDecive) { moveDir.x =Input.GetAxis("Horizontal");// get result of AD keys in X moveDir.x =Input.GetAxis("Horizontal"); moveDir.y =Input.GetAxis("Vertical");// get result of WS keys in Y moveDir.y =Input.GetAxis("Vertical"); // move this object at frame rate independent speed: tiltAroundY =Input.GetAxis("Horizontal")* tiltAngle; } else { moveDir.x = horizontalMovement;// get result of AD keys in X moveDir.y = verticalMovement;// get result of WS keys in Y } }
Hey @CameronB999 I have attached your script to Game object but it is not working not displaying message in console Steps I have followed -- Created new Unity 2d project -- Created new game object -- Applied your script to that object -- Run the project -- Tried to swap by using mouse on object -- Checked console But nothing displayed in console Am I missing anything or doing something wrong Please help