Game Dev Cheat Sheet

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.delta

Common Patterns

Quick comparison of touch operations across Unity Legacy, Unity Enhanced Touch, and Godot.

GestureUnity LegacyUnity EnhancedGodot
Detect any touchInput.touchCount > 0Touch.activeTouches.Count > 0event is InputEventScreenTouch
Get touch positionInput.GetTouch(0).positionTouch.activeTouches[0].screenPositiontouch_event.position
Touch begantouch.phase == TouchPhase.Begantouch.phase == UnityEngine.InputSystem.TouchPhase.Begantouch_event.pressed == true
Touch endedtouch.phase == TouchPhase.Endedtouch.phase == UnityEngine.InputSystem.TouchPhase.Endedtouch_event.pressed == false
Touch moved / dragtouch.phase == TouchPhase.Movedtouch.phase == UnityEngine.InputSystem.TouchPhase.Movedevent is InputEventScreenDrag
Touch delta / velocitytouch.deltaPositiontouch.deltadrag_event.velocity
Multi-touch countInput.touchCountTouch.activeTouches.CountHandle in _input per event
Finger identitytouch.fingerIdtouch.finger.indextouch_event.index