UI Button OnClick Sensitivity for High DPI Devices

I’ve got a Unity project running on a Samsung Galaxy S5, and users are having issues pressing buttons.

They need to repeatedly click on any button using the OnClick handler. I believe this is because of very small movements in their finger when they touch the device reading as scrolling rather than a simple touch. Adding an OnPointerDown event trigger of course avoids the issue…

Unfortunately, some of my buttons are on items that take up large chunks of a ScrollRect. This means that I can’t easily switch to using EventTriggers to simply capture OnPointerDown - that would unnecessarily trigger the button when the person is actually scroll-dragging.

Is there any way I can change the ‘scroll’ sensitivity within the Button generally? I’d like to adjust it to suit Screen.dpi, since most devices with a higher resolution screen have an accompanying increase in touch resolution.

Looking at Unity’s UI implementation (on tag 5.3) I’ve found that (1) is called by (2) which uses pixelDragThreshold attribute defined by the current EventSystem instance in the scene…

A possible (and maybe the simplest) solution would be to use a script which will change that threshould based on the screen PPI (Screen.dpi) of each device.

1. private static bool ShouldStartDrag(...) @ PointerInputModule.cs : 228
2. protected virtual void ProcessDrag(...) @ PointerInputModule.cs : 248

The following script does the drag threshold adaptation, put this in your event system game object:

using UnityEngine;
using UnityEngine.EventSystems;

public class DragCorrector : MonoBehaviour
{
    public int baseTH = 6;
    public int basePPI = 210;
    public int dragTH = 0;

    void Start()
    {
        dragTH = baseTH * (int)Screen.dpi / basePPI;

        EventSystem es = GetComponent<EventSystem>();

        if (es) es.pixelDragThreshold = dragTH;
    }
}

Here’s a very simple script to check the device’s PPI… you can run this on different phones to see if Unity is calculating it right:

using UnityEngine;
using UnityEngine.UI;

public class PPIViewer : MonoBehaviour
{
    public Text label;

    void Start()
    {
        if (label != null)
        {
            label.text = "PPI: " + Screen.dpi.ToString();
        }
    }
}

This code is more efficient for me:
link text

public class DragThresholdUtil : MonoBehaviour {
  void Start () {
    int defaultValue = EventSystem.current.pixelDragThreshold;		
    EventSystem.current.pixelDragThreshold = 
            Mathf.Max(
                 defaultValue , 
                 (int) (defaultValue * Screen.dpi / 160f));
  }
}

Nice little fix. Would you be OK with me adding this to the UI extensions project? Should prove valuable.

Try to increase the Drag Treshold in the Event System to about 16 :slight_smile: .

I came up to following blog post when I was solving this issue:

Unity UI Drag Threshold

It introduces script that update Drag Threshold according to DPI.