quot;Touch {touch.touchId} began at {touch.screenPosition}"); break; case TouchPhase.Moved: case TouchPhase.Stationary: break; case TouchPhase.Ended: case TouchPhase.Canceled: Debug.Log(quot;Touch {touch.touchId} ended phase={touch.phase}"); break; } } } } ``` The alias `using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch` is the official sample's habit, so this struct does not collide with `UnityEngine.Touch`. ## 2.2 Touches vs fingers vs actions Official `Touch` remarks (1.20.1): a **touch** is one contact-state change (Began / Moved / Ended / Canceled). A **finger** is the Nth contact on the screen and stays that slot as the contact moves. `Touch.activeTouches` is every touch that is ongoing **or ended this frame**. A contact that begins and ends in the same hardware update can surface as Began this frame and Ended next - so the count can exceed the number of physical fingers for a moment. Useful official properties, once support is enabled (accessing them otherwise throws `InvalidOperationException`): | Member | Role | |---|---| | `Touch.activeTouches` | Poll this in `Update` | | `touch.touchId`, `touch.phase`, `touch.screenPosition` | Identity, phase, position | | `touch.startScreenPosition`, `touch.delta`, `touch.startTime`, `touch.time` | Gesture math | | `touch.finger` | The `Finger` for this contact | | `Touch.activeFingers` / `Touch.fingers` | Active only, or all slots | | `Touch.onFingerDown` / `onFingerMove` / `onFingerUp` | Event alternative to polling | | `touch.pressure`, `touch.radius` | **Device-dependent**; pressure may be 0 if unsupported | | `touch.history` | History for this contact; official default history length can be **zero** until you opt into keeping it (`maxHistoryLengthPerFinger`) | Confirm `maxHistoryLengthPerFinger` in 1.20.1 IntelliSense if you need a swipe history; do not assume history is already recording. Enhanced Touch and `InputAction` can run **side by side**, but Enhanced Touch is a polling API - official remarks say it is not itself the Actions system. Prefer Actions + on-screen controls for player Move. Prefer Enhanced Touch for debug and custom gestures you are prepared to write tests for. ## 2.3 Where the Simulator will lie to you The Device Simulator (part 4) can only inject **one** finger. A two-finger gesture written against `Touch.activeTouches` will look "broken" in the Simulator even when the code is fine. Test multitouch on a phone, or with whatever **Input System** touch-simulation option your 1.20.x Input Debugger actually exposes (confirm in the installed package; do not copy a flag name from a different Input System major version). ## 2.4 Exercise Add `TouchDebugOverlay` to an empty scene, enable Enhanced Touch, enter Play Mode, and drag in the Game view or Device Simulator. Log `touchId` and `phase`. Then comment out `Enable()` and confirm you get the official `InvalidOperationException` (or enable-required behavior) when polling `activeTouches` - so you remember the switch. ## Sources - Touch polling (1.20.1): https://docs.unity3d.com/Packages/[email protected]/manual/touch-polling.html - `EnhancedTouchSupport` (1.20.1): https://docs.unity3d.com/Packages/[email protected]/api/UnityEngine.InputSystem.EnhancedTouch.EnhancedTouchSupport.html - `Touch` (1.20.1): https://docs.unity3d.com/Packages/[email protected]/api/UnityEngine.InputSystem.EnhancedTouch.Touch.html