Touch Input Reference
Unity Legacy, Enhanced Touch, and Godot touch APIs with copy-paste code.
Basic Touch Detection
Unity's legacy Input class provides Input.touchCount and Input.GetTouch(0) for reading touch data. Each touch has a phase: Began, Moved, Stationary, Ended, or Canceled.
// Unity Legacy Input: basic touch detection
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
Debug.Log("Finger touched at " + touch.position);
break;
case TouchPhase.Moved:
Debug.Log("Finger moved to " + touch.position);
break;
case TouchPhase.Stationary:
Debug.Log("Finger held at " + touch.position);
break;
case TouchPhase.Ended:
Debug.Log("Finger lifted at " + touch.position);
break;
case TouchPhase.Canceled:
Debug.Log("Touch cancelled");
break;
}
}Enhanced Touch API (Unity 2019.4+)
The new Input System package includes Enhanced Touch, which must be explicitly enabled with EnhancedTouchSupport.Enable(). It provides Touch.activeTouches and the Finger class for persistent finger tracking across frames. The new Input System also supports touch via Touchscreen.current.
// Unity Enhanced Touch (Input System package, 2019.4+)
using UnityEngine.InputSystem.EnhancedTouch;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
void OnEnable()
{
EnhancedTouchSupport.Enable();
}
void OnDisable()
{
EnhancedTouchSupport.Disable();
}
void Update()
{
foreach (Touch touch in Touch.activeTouches)
{
Debug.Log($"Touch {touch.finger.index} at {touch.screenPosition}, phase: {touch.phase}");
}
}
// You can also access touch via Touchscreen.current:
// using UnityEngine.InputSystem;
// var touchscreen = Touchscreen.current;
// if (touchscreen != null && touchscreen.primaryTouch.press.isPressed)
// {
// Vector2 pos = touchscreen.primaryTouch.position.ReadValue();
// }Tap Detection
A tap is a short touch that begins and ends quickly without significant movement. Track the start time on TouchPhase.Began and check the duration on TouchPhase.Ended.
// Unity Legacy: tap detection
private float tapTimeThreshold = 0.2f;
private float tapStartTime;
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
tapStartTime = Time.time;
}
else if (touch.phase == TouchPhase.Ended)
{
float tapDuration = Time.time - tapStartTime;
if (tapDuration < tapTimeThreshold)
{
OnTap(touch.position);
}
}
}
}
void OnTap(Vector2 position)
{
Debug.Log("Tapped at " + position);
}Swipe Detection
Detect swipe direction by comparing the start and end positions. Calculate the delta vector, check its magnitude against a threshold, then use the dominant axis to determine whether the swipe was horizontal or vertical.
// Unity Legacy: swipe detection
private Vector2 swipeStart;
private float swipeThreshold = 50f; // minimum distance in pixels
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
swipeStart = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
Vector2 delta = touch.position - swipeStart;
if (delta.magnitude < swipeThreshold)
return; // too short, ignore
// Determine direction from the dominant axis
if (Mathf.Abs(delta.x) > Mathf.Abs(delta.y))
{
Debug.Log(delta.x > 0 ? "Swipe Right" : "Swipe Left");
}
else
{
Debug.Log(delta.y > 0 ? "Swipe Up" : "Swipe Down");
}
}
}
}Pinch to Zoom
Pinch-to-zoom requires two simultaneous touches. Track the initial distance between the two fingers, then compare it to the current distance each frame to calculate a scale factor.
// Unity Legacy: pinch to zoom
private float initialPinchDistance;
private float initialZoom;
void Update()
{
if (Input.touchCount == 2)
{
Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
if (touch0.phase == TouchPhase.Began || touch1.phase == TouchPhase.Began)
{
initialPinchDistance = Vector2.Distance(touch0.position, touch1.position);
initialZoom = Camera.main.orthographicSize; // or fieldOfView for perspective
}
else if (touch0.phase == TouchPhase.Moved || touch1.phase == TouchPhase.Moved)
{
float currentDistance = Vector2.Distance(touch0.position, touch1.position);
float scaleFactor = initialPinchDistance / currentDistance;
Camera.main.orthographicSize = Mathf.Clamp(initialZoom * scaleFactor, 2f, 20f);
}
}
}Multi-Touch
Loop over all active touches to handle multiple fingers simultaneously. The legacy API uses an index-based loop, while Enhanced Touch provides a foreach-friendly collection and persistent Finger references.
// Unity Legacy: loop over all active touches
void Update()
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);
Debug.Log($"Touch {touch.fingerId} at {touch.position}, phase: {touch.phase}");
}
}
// Unity Enhanced Touch: loop with Finger tracking
using UnityEngine.InputSystem.EnhancedTouch;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
void Update()
{
foreach (Touch touch in Touch.activeTouches)
{
// Each touch has a .finger reference for tracking identity
Debug.Log($"Finger {touch.finger.index} at {touch.screenPosition}");
}
// Access specific fingers directly
// Finger firstFinger = Touch.activeFingers[0];
// Debug.Log($"Finger 0 current touch: {firstFinger.currentTouch.screenPosition}");
}Godot Equivalents
Godot handles touch through its event system. Use InputEventScreenTouch for tap and release events, and InputEventScreenDrag for finger movement. Godot 4 also supports InputEventMagnifyGesture and InputEventPanGesture for pinch and pan.
# Godot: touch and drag input
extends Node2D
func _input(event: InputEvent) -> void:
# Tap / release
if event is InputEventScreenTouch:
var touch_event := event as InputEventScreenTouch
if touch_event.pressed:
print("Touch began at ", touch_event.position)
else:
print("Touch ended at ", touch_event.position)
# Finger drag / movement
if event is InputEventScreenDrag:
var drag_event := event as InputEventScreenDrag
print("Drag at ", drag_event.position, " velocity: ", drag_event.velocity)
# Pinch and pan gestures (Godot 4)
func _input(event: InputEvent) -> void:
if event is InputEventMagnifyGesture:
var magnify := event as InputEventMagnifyGesture
# magnify.factor > 1.0 = zoom in, < 1.0 = zoom out
camera.zoom *= magnify.factor
if event is InputEventPanGesture:
var pan := event as InputEventPanGesture
camera.position += pan.deltaCommon Patterns
Quick comparison of touch operations across Unity Legacy, Unity Enhanced Touch, and Godot.
| Gesture | Unity Legacy | Unity Enhanced | Godot |
|---|---|---|---|
| Detect any touch | Input.touchCount > 0 | Touch.activeTouches.Count > 0 | event is InputEventScreenTouch |
| Get touch position | Input.GetTouch(0).position | Touch.activeTouches[0].screenPosition | touch_event.position |
| Touch began | touch.phase == TouchPhase.Began | touch.phase == UnityEngine.InputSystem.TouchPhase.Began | touch_event.pressed == true |
| Touch ended | touch.phase == TouchPhase.Ended | touch.phase == UnityEngine.InputSystem.TouchPhase.Ended | touch_event.pressed == false |
| Touch moved / drag | touch.phase == TouchPhase.Moved | touch.phase == UnityEngine.InputSystem.TouchPhase.Moved | event is InputEventScreenDrag |
| Touch delta / velocity | touch.deltaPosition | touch.delta | drag_event.velocity |
| Multi-touch count | Input.touchCount | Touch.activeTouches.Count | Handle in _input per event |
| Finger identity | touch.fingerId | touch.finger.index | touch_event.index |