# 3. On-Screen Stick and Isolated Actions Part of [[Mobile Input and Touch]]. Prev: [[2. Enhanced Touch Polling]]. Next: [[4. Device Simulator and Safe Area]]. This is the official virtual-gamepad path. Namespace: `UnityEngine.InputSystem.OnScreen`. Manuals (1.20.1): [create an on-screen stick](https://docs.unity3d.com/Packages/[email protected]/manual/create-on-screen-stick-control.html), [create an on-screen button](https://docs.unity3d.com/Packages/[email protected]/manual/create-on-screen-button-control.html). ## 3.1 On-screen stick (official steps) 1. Create a uGUI **Image** (the visible knob or a dedicated hit area). 2. Add the `OnScreenStick` component (`Add Component > Input > On-Screen Stick`). 3. Set **Control Path** (`controlPath`, inherited from `OnScreenControl`) to a **`Vector2` control**. Official example: `<Gamepad>/leftStick`. The device type in the path is the virtual device the component creates. 4. Leave an **EventSystem** in the scene, with the Input System UI module already discussed in [[4. UI Input and XR Input]]. Official behavior: the stick starts on `IPointerDownHandler.OnPointerDown`, moves on `IDragHandler.OnDrag` inside a box centered on the pointer-down point whose edge length is **Movement Range**, and stops on `IPointerUpHandler.OnPointerUp`. A `movementRange` of 50 means 25 pixels up, down, left, and right of the pointer-down point (official manual wording). If you want your own started / stopped callback, implement those EventSystem interfaces on **another** component on the same GameObject - do not replace the stick's handlers. ### Isolated input (you almost always want this) Official `OnScreenStick` remarks and the "Isolate stick controls" manual section: the stick **simulates** events from the device in `controlPath`. If `PlayerInput` has auto-switch on (`neverAutoSwitchControlSchemes` false), those simulated Gamepad events can switch the paired device away from the pointer that is dragging the stick. The pointer action is then **cancelled**, `OnPointerUp` runs, and the stick **jumps back to center** while the thumb is still down. **Fix:** enable **Use Isolated Input Actions** (`useIsolatedInputActions = true`). Official: the stick then uses a **local** set of input actions, so device switching does not cancel the drag. Downside, official: pointer actions are duplicated on the stick and on any UI action asset. If you do not specify Pointer Down / Pointer Move bindings, 1.20.1 defaults include (among others) `<Mouse>/leftButton`, `<Pen>/tip`, `<Touchscreen>/touch*/press`, `<Mouse>/position`, `<Pen>/position`, `<Touchscreen>/touch*/position` - confirm the exact default list in the manual if you override them. You might also need to keep Mouse / Pen / Touchscreen / XR controllers from sitting in a **concurrent** control scheme of the simulated Gamepad (official remarks; typo "concurent" / "Touchsceen" on the API page). In practice for this course: isolated mode on, and do not also bind those pointers into the Gamepad scheme. ### Other official properties (confirm in Inspector) - `movementRange` - how far the knob travels (see above). - `behaviour` - official API: how the stick moves relative to its origin and the press position. Remarks name **`ExactPositionWithDynamicOrigin`**, which uses `dynamicOriginRange`: a first press *inside* that radius places the origin there; a press outside is ignored. Confirm the other `OnScreenStick.Behaviour` enum values in 1.20.1 IntelliSense before you depend on them; this series does not invent the rest of the enum. - `dynamicOriginRange` - only applies for that dynamic-origin behaviour. ## 3.2 On-screen button (official steps) 1. Add a uGUI **Button**. 2. Add `OnScreenButton`. 3. Set `controlPath` to a **`Button` control**, official example: `<Gamepad>/buttonSouth`. Official behavior: pointer-down sets the control to **1**, pointer-up sets it to **0**. There is no `useIsolatedInputActions` on the 1.20.1 `OnScreenButton` API page - that property is documented on `OnScreenStick`. If a button misbehaves with auto-switch, confirm in 1.20.1 whether a later option appeared; do not copy the stick property onto the button in code unless IntelliSense shows it. ## 3.3 Canvas setup notes - Anchor the stick in a **thumb corner**, not the middle of a 16:9 canvas you never tested in portrait. - Respect **safe area** (part 4) so a home indicator does not eat the stick. - The Image needs to be raycast-targetable. A fully transparent Image still works if Raycast Target stays on; a disabled Graphic does not receive EventSystem events. - One Canvas for HUD + sticks is fine. Do not put the stick under a full-screen Image that blocks every pointer event from reaching the Game view you thought you were testing. ## 3.4 Exercise In a blank scene: Canvas, EventSystem, Image + `OnScreenStick` with `<Gamepad>/leftStick`, `movementRange` 80, `useIsolatedInputActions` on. Add a `PlayerInput` set to the Gamepad scheme with auto-switch **on**, and a script that logs the Move action. Drag the stick: it must not snap back mid-drag. Then turn isolated mode **off** and reproduce the official snap-back so you know what the checkbox is for. ## Sources - https://docs.unity3d.com/Packages/[email protected]/manual/create-on-screen-stick-control.html - https://docs.unity3d.com/Packages/[email protected]/manual/create-on-screen-button-control.html - `OnScreenStick` 1.20.1: https://docs.unity3d.com/Packages/[email protected]/api/UnityEngine.InputSystem.OnScreen.OnScreenStick.html - `OnScreenButton` 1.20.1: https://docs.unity3d.com/Packages/[email protected]/api/UnityEngine.InputSystem.OnScreen.OnScreenButton.html