[UI Toolkit] Fix Mobile Touch Movement with Pointer Capture
Solution
Unity 2021.3.x - Unity 6.3.x
Published Sun, May 10
Touch input on mobile devices often fails to trigger PointerMoveEvent or PointerDownEvent for draggable elements when using the New Input System and UI Toolkit. While mouse interactions in the Editor function correctly, touch movement is frequently ignored once the finger leaves the initial boundaries of your visual element, causing interrupted dragging behavior.
The default behavior of PointerMoveEvent for touch input in the UI Toolkit is to only fire while the touch remains within the original bounds of your visual element. This differs significantly from mouse input, which often maintains an active state more loosely. This limitation prevents smooth dragging on mobile devices because a fast or wide gesture often exceeds the initial hit-box of the element.
To enable reliable dragging, you must utilize the pointer capture system. This programmatically locks the pointerId to your visual element, ensuring that all subsequent movement and release events are routed to it regardless of the current touch position.
- Within the
PointerDownEventcallback, invokeCapturePointeron your visual element using the pointerId from the event arguments. - During the
PointerMoveEvent, verify the element still has focus by checkingHasPointerCapturewith the pointerId before applying translation logic. - Within the
PointerUpEventcallback, invokeReleasePointerto free the pointerId and allow other elements to receive input.
Additional Tips
- Listen for
PointerCaptureOutEventto handle cases where the system cancels the touch (e.g., an incoming phone call or OS gesture). - Ensure your visual element has a
usageHintsset toUsageHints.DynamicTransformif it moves frequently to optimize performance. - Verify that the
pickingModeproperty of your visual element is set toPickingMode.Positionso it can intercept pointer events.
TL;DR
For consistent touch interaction, explicitly manage pointer state by calling CapturePointer on your visual element during the PointerDownEvent. This ensures the pointerId is tracked even when movement occurs outside the element bounds.
Related Posts Haven't quite found a solution to your problem? We think these posts might help you.
Content inspired by a Unity discussion post.