How to calculate swipe speed on iOS

Hi there. I was wondering if anyone could help me figure out how I would go about calculating a swipe on the iPhone? I searched and found a question similar to mine but didn’t really help me out.

What I am trying to do is move my camera a certain distance after the user lifts their finger which is calculated from the swipe speed.

Any help is appreciated thanks.

#Note, this is an extremely old answer!

“Unityscript” is no longer available, use c#. You can follow the concepts in this post.

Note for anyone reading this in the future: If you’re getting started with Unity don’t forget you could you just use one of the many gesture handling packages, which are easily available on the asset store. To save you a lot of time!

#These days use raycaster…

these days, in practice you have to use the “raycaster method” not to step over UI. here is a huge amount of code for example

It’s hard to do things like this well. You can easily get a quick fix but it’s hard to take care of all the detail.

{A huge issue is that in any real app you need to worry about stray fingers touching the screen. That is a completely normal part of developing for tablets. Users today in 2012 won’t live with apps that don’t have good engineering to cover issues like your thumbs may happen to be touching the sides of the screen where you’e holding the ipad.}

In general terms it’s just the distance the finger travelled against the time taken. Fortunately these are both easily available. Generally, there is no reason at all to ever bother looking at the actual values of the start and end point, you only want to know how far the swipe was. This is given to you in “deltaPosition”. So in a helloWorld program you might do something like this:

Input.touches[0].deltaPosition / Input.touches[0].deltaTime

So in general terms you might have something like this …

// the following code is just "helloWorld" code to get you going
// if you are learning about how to engineer for touch screen.
// don't expect to be able to use this in the next monsters ate
// my condo !  :)

function Update()
 // we'll adopt an incredibly simplistic approach here
 // to begin with ignore everything unless only one touch
 // on the screen
 if ( Input.touches.Length != 1 ) return;
 // we will only bother thinking about "moves" with the finger.
 // we don't even care about concepts like where did it start,
 // end, whatever.
 if ( Input.touches[0].phase != TouchPhase.Moved ) return;
 // so, deal with a 'TouchPhase.Moved' concept here:
 // do not actually use the following code, it is useless!!
 // just for a demo.
 processOneSmallMove( Input.touches[0].deltaPosition
           / Input.touches[0].deltaTime );

function processOneSmallMove ( noticeThisIsAVector :Vector2 )
 // you have to write this routine
 // don't forget this is possibly just one microscopic
 // part of a "whole swipe" your user has made.
 // entirely depending on what you are doing, you may
 // or may not have to consider that concept.
 // if you're just say "adding force" it's usually
 // great just to do so for each "little piece" here.

However in practice … this is of no value to you at all !!

If (strangely enough!) you are doing a business app or something and you need the speed “on the glass”. What you’ll have to do is get the speed measured in “screen size”

Again, whenever you see any code for this sort of thing in the real world it’s always screensize -this and screensize -that, screensize per second, screeheight per second, and so on.

There are all sorts of different pixel-counts of glass on tablets (what do you call touch-points anyway, tixels??) So it’s completely useless, “meaning-less”, to run around with pixel measurements. You have to work in screen-size-land. So in practice you would do something vaguely like this

var distanceMeasuredInScreenWidths:Vector2;
distanceMeasuredInScreenWidths =
    Input.touches[0].deltaPosition / Screen.width;

// (NB that's a bit cheap - better to use
// the diagonal measure of the screen)

var speedMeasuredInScreenWidthsPerSecond:float;
speedMeasuredInScreenWidthsPerSecond =
    distanceMeasuredInScreenWidths / Input.touches[0].deltaTime;

// NOTE! when you do this for real,
// do not forget some just-in-case code along these lines...
// if Input.touches[0].deltaTime == 0.0 return;

    speedMeasuredInScreenWidthsPerSecond );

// SWPS === screen widths per second

function processOneSmallMoveMeasuredInSWPS (
    noticeThisIsAVector :Vector2 )
// so for example 1.0 is a fairly slow swipe that would take
// one second to cross the whole device, whatever device is

// don't forget this is possibly just one microscopic
// part of a "whole swipe" your user has made.
// entirely depending on what you are doing, you may
// or may not have to consider that concept.
// if you're just say "adding force" it's usually
// great just to do so for each "little piece" here.

So that will give you the speed “on the glass” in a meaningful way.

Observe - immediately we have real “meaning”. You might be chatting with your colleagues and decide, if the swipe on a button is happening at less than, let’s say, 0.5 “screen widths per second”, you might think that should be just put in the stupid basket, ie it is so bloody slow it is certain the user did not mean a button swipe. Conversely, you might feel that 100 screenwidth per second is just stupid and was obviously some sort of stray touch, some dumbass cat running over the screen, or whatever, and you should ignore all such values.

But unfortunately that’s not much good to you!

As a game programmer, all that matters to you is the speed of their finger IN THE GAME right?

Now you could just add a “stupid factor” and try different numbers (0.01, 13.8, 11102, 1.2334) until the force yo are adding to the spaceship seems OK. But that’s no good, in a game engine you must deal entirely with real measures, real masses, real horsepower and so on.

So in Monsters Ate My Condo the guys had to worry about the speed of your finger moving across the “condos”. For example, those dudes would have had some “real” size of the condo blocks, let’s say they are 2 meters across. Then, when handling swipes, they would very much need the speed in that concept, so a fast swipe might be 25 m/s or a slow swipe might be say 8 m/s. In a typical 2D game you need the speed of their finger “on the starry background”. If you are pushing an object around, you need the speed - well you need the actual speed of that object, say km/h or whatever if it’s a car, say.

So how the hell do you get the speed “in the game”? thank God, it is fairly easy to do thanks to the miracle of Unity3D.

if you think about it all you have to do is this --where the touch starts, find out where that is in the real world ! And where the touch ends, find out where that is in the real world! You simply do that using the usual beautiful raycast mechanism in Unity3D.

So conceptually, for each little drag you just raycast in to your real universe from the glass, to find out the “real” drag the happy user made! No wonder people pay a buck for this stuff in the app store!

I apologise because I did not “forum format” this code, ie, I did not break all the lines to the small width needed here. The code block will scroll to the right. You may want to copy to your text editor because it is annoying looking at code blocks that are cut off on the right!!

// in this code we are getting much more closer to usable touch interaction,
// coz we are moving from the GLASS to the REAL UNIVERSE
// to quote a famous film this is the first step in to a bigger world !

private var theCam:Camera;

private var yellowRay: Ray;
private var theHit : RaycastHit;
private var ignoreMask:int;

private var onTHINGPointBegin:Vector3;
private var onTHINGPointEnd:Vector3;

// please note, i used "THING" in this example code.
// for example ...... in the code I found this in, it was "Cloud",
// in that title the user would swipe on "clouds" for some reason
// so the variables were of course named onCloudPointBegin, and so on.
// clouds are in fact about 2000 meters long, so in that example the
// ultimate values would be something like, say 500 m/s or whatever
// ie the user would be swiping (in the real world) at say 500 m/s

private var startedAtGlasswise:Vector3;

function Update()
 if ( Input.touches.Length == 0 ) return;
 // so find out where they touched on our THING
 // for instance, if this is a 2.5D game, you'd have a nice tidy plane
 // in a relevant location for the user to swipe on.
 // if this is a race game they may be swiping on the track, on
 // a control panel, or whatever the case may be.
 // so figure out where the hell this swipe ended in the real world
 yellowRay = theCam.ScreenPointToRay( Input.touches[0].position );
 if ( ! collider.Raycast (yellowRay, theHit, 10.0 ) ) return;
 // very typically you will have to ignore clicks on other layers  ...
 // if ( Physics.Raycast ( theCam.ScreenPointToRay( Input.touches[0].position ), theHit, 20.0, ignoreMask) ) return;
 // so we can get the END point (REAL world) from that raycast. we'll usually need it later so let's get it
 onTHINGPointEnd = theHit.point;
 // in this trivial example code we will bother only with moveds...
 if ( Input.touches[0].phase != TouchPhase.Moved ) return;
 // for business apps if you want the speed on the glass, you can merely do this
 // moveLikeThis( deltaPosition measured in screen widths / Input.touches[0].deltaTime );
 // that's useless, so we have to figure out the "real world values". so let's do that...
 // we already have onTHINGPointEnd, so let's get onTHINGPointBegin
 // first figure out the positions on the GLASS. then find those REAL WORLD
 // position inside our game engine universe.
 startedAtGlasswise = Input.touches[0].position - Input.touches[0].deltaPosition;
 yellowRay = theCam.ScreenPointToRay( startedAtGlasswise );
 onTHINGPointBegin = onTHINGPointEnd; // our default political position
 if ( collider.Raycast (yellowRay, theHit, 10.0 ) )
 onTHINGPointBegin = theHit.point;
 // so now we have the true real-world velocity...hooray!
 // all you have to do now is this ...
 // (onTHINGPointEnd - onTHINGPointBegin) / Input.touches[0].deltaTime
 // but first, some typical real-world exclusions and other problems
 // very commonly, you will have some "physical" exclusions, example:
 // the user plain cannot use the left tenth of the screen, for example:
 if ( startedAtGlasswise.x < 0.1 * Screen.width ) return;
 // in most situations you would very likely have many exclusions of that nature.
 // for instance, you can't swipe in the wrong direction .. who knows
 // just to avoid any confusion: in this code startedAtGlasswise is measured 
 // IN THE PIXELS (tixels??) of the screen.  in any code where you were doing swipes
 // based on the screen ("business apps"), you would never do that -- you would convert
 // it to "screen widths fraction" and use that everywhere.
 // of course, for Unity3D to use functions such as ScreenPointToRay, you use the
 // physical touch-screen pixels, which is what we are doing here
 // so finally we can process the swipe (remembering it's a "swipe fragment")
 // simply using the REAL WORLD VELOCITY ... distance travelled in the real world
 // divided by time of the swipe
 if ( Input.touches[0].deltaTime == 0.0 ) return; // just in case
 moveLikeThisInRealWorld( (onTHINGPointEnd - onTHINGPointBegin) / Input.touches[0].deltaTime );

function moveLikeThisInRealWorld( dd:Vector3 )
 // for instance:
 // if you are "dragging an object around with your finger"
 // in that example your job is entirely DONE, just move the object
 // by this vector. it's really that simple and beautiful.
 // (so in the cloud example, incredibly, you could simply move the
 // cloud, UFO or whatever it was by say 728 meters or whatever value
 // emerges from this "glass to real universe" swiping code)
 // To be clear we've looked at velocity here, of course often you may need
 // just the position change, i.e not considering the time.
 // however, in practice you almost always have to consider in some way
 // the time taken, to see if it is meaningful


The conceptual takeaway:

Your user is swiping IN THE REAL UNVIERSE, as a rule they are not swiping on the glass. (Very rare exception are some business apps and the like.)

Note that if for example your user is swiping “on a button” you still do exactly everything described above exactly the same. how big is a button, I say it’s about 7 cm across. You will end up with a value like “28 cm/s”, say. You will then have to THINK about the real world and decide what to do. For instance, in my opinion, if a user is swiping a swipe-button (think of the light switch in your living room) at say 4 cm/s … I say there is probably something oerhaps mentally wrong with the user (they are having a drifty “beautiful mind” moment), or maybe it’s just a child, or maybe it’s the users finger or other appendage accidentally touching the screen. As well as the magnitude, you would consider the direction. If the bloody user is swiping the swipe switch at right angles (some users!) you would have to deal with that with intelligence one way or another. As a programmer annoyingly you have to add intelligence dealing with interactions, I mean you can rarely just deal with things “dumbly” you have to really consider all sorts of stuff, what was “meant” by this touching the glass business.

The point is that once you do everything in 'real world", and you must do that pretty much, it is vastly easier. In the “cloud” example everything is beautiful and intelligent when measured in km/s because that’s (obviously!) how you move real-world clouds around with your finger. If as developers, my mates had left it as “glass pixels” or something, well we all might as well just sit around unwashed all day, that is bad.

So moving to the “real world” is the first step of putting intelligence, even heuristics or AI, in to processing the physical touches on the screen.

Don’t forget that tragically all of the above is merely “pointers to the beginning of” handling appendages touching the screen.

The big problem is the massive amount of work to handle more than one touch and stray touches and so on.

{Say your user does a long drag with one finger, and during that drag lazily adds another fingertip – what do you do? What about if they 'change" fingertips during that process? What do you do?

Say you’re doing an app for small children, so you totally want to allow “child’s hand” moves (God knows how many touches, knuckles, fingers, palms), rather than pure adult one-touches. OK so you carefully track ALL the sub-drags, how do you then construct the “overall drag the child meant” Is it the average? mean? biggest? or what??}

How do you know if it’s just some joker holding the screen edges with their thumibs, etc? Should you exclude that? Bring up a warning? Don’t ask me, go ask your Dad!

Store the position at the start of the touch. Store the position at the end of the touch. The difference between is the length of the drag. Remember to consider different resolutions will give different measurements i.e. 480x320, 960x640, 1024x768,2048x1536 . Or just record the changes in deltaPosition.

Look into the Input states for iOS :