Drag Threshold not working properly only with some iPhones models!

Hello everyone!

I came across a very strange bug.
I have an iPhone 11 Pro and I have been building the project onto it from the beginning and it worked perfectly. Once I released my game to the public, I got some reports that the functionallity that alternates between “dragging” and “selecting” was being an issue (Probably because the code thinks the person is dragging instead of selecting).

So, I tested it out on three different iPhoneX’s (Xs and X) and one iPhone 7 and it really has the issue the users were claiming.

What is weird is that it works perfectly on Android phone’s and in mine iPhone 11 Pro.

I am posting this because I have no clue of what this might be. I already have the “Drag Threshold Fix Script” added to my EventSystem.

I have and old post in which I explain in detail exactly what I did regarding this “dragging and selecting” code.

I think you will have to instrument your drag code to figure out what’s going on.

Some things to try: put visible proxy crosshairs where the code thinks the touch is

That way if Apple is filtering it you can tell what positions your code is getting

Also spit out some info when the states change between your drag / tap code.

Have you tried in the Xcode emulator?

Hello, @Kurt-Dekker

Nice suggestions. I’m going to implement them and post the results.

I didn’t understand why you asked this. Why would I use the emulator? To see if it also has problems selecting with a mouse?

I’m thinking if you just want to try it on a broader range of devices that you don’t necessarily possess.

So, it was as suspected. I printed the state of dragging/selecting and when I was trying to select, it was in the drag state.

I also used a crosshair as you suggested and it worked fine. The place of the touch was correct.

Any idea what might be causing this?

Drag state:

if (Input.touchCount > 0)
    {
      if (Input.GetTouch(0).phase == TouchPhase.Ended)
        master.TransitionToState(master.OffState);

Select State:

 if (Input.touchCount > 0)
    {
      if (Input.GetTouch(0).phase == TouchPhase.Ended)
      {
        //SELECTION CODE
      }
      else if (Input.GetTouch(0).phase == TouchPhase.Moved)
        master.TransitionToState(master.DragState);
      else return;
    }

[EDIT]
I found this, which made me a bit worried:
https://stackoverflow.com/questions/50756884/unity-why-iphone-6-and-7-behaves-differently-to-touch-input

Just added some code that gets the position of the touch when it begins and when it stops dragging to see if I could add an error margin to correct this but the result was curious.
It goes to the “drag state” even though both positions are the same! I have no idea why the touch.phase is becoming TouchPhase.Moved given that starting and ending positions are exactly the same (even the decimals).
This is getting very awkward… I have no idea how to proceed.

Are you comparing floating point numbers for equality? You should compare them for approximately equal, or as we spoke in the other channel, a guard amount to avoid finger wiggle.

With floating point numbers, two numbers that display identically can still be different internally and fail equality check. That’s why we never compare floating points for equality, only less than or equal, or compare difference for below a value.

For the “guard” distance, I usually consider anything less than 5% of the small axis of the screen (in pixels) to be not moved. Some cheap android devices have noisy touch input, so the finger appears to jitter around a bit.

float minDragDistance = Mathf.Min( Screen.width, Screen.height) * 0.05f;

if (distanceDragged >= minDragDistance)
{
  // consider it a drag
}

Thanks for the reply @Kurt-Dekker .

I came to the same conclusion and solved it in a similar way just moments ago. I just think this is kind of weird still… I can’t see a case in which a developer would use a built in function called Touchphase.MOVED that would not work properly due to jitters.

But anyway, as always, appreciate the help!

1 Like