# 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