File size: 5,041 Bytes
40c0886 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | # Unity Input System
Unity offers two input systems:
1. **Input Manager (legacy)** -- `Input.GetAxis`, `Input.GetKeyDown`. The
default in 2022.3 LTS. Used by every generated script in this project.
2. **Input System package** -- the new event-driven API. Available via the
`com.unity.inputsystem` package.
## Input Manager (legacy)
### Axes
The legacy system reads virtual axes defined in
`Edit > Project Settings > Input Manager`. The defaults include:
| Axis name | Default keys |
|---------------|---------------------------------|
| `Horizontal` | A/D, Arrow Left/Right |
| `Vertical` | W/S, Arrow Up/Down |
| `Mouse X` | Mouse delta X |
| `Mouse Y` | Mouse delta Y |
| `Jump` | Space |
| `Fire1` | Left Ctrl / Mouse 0 |
| `Fire2` | Right Alt / Mouse 1 |
| `Fire3` | Left Shift / Mouse 2 |
### Reading axes
```csharp
float x = Input.GetAxisRaw("Horizontal"); // -1, 0, +1 (no smoothing)
float y = Input.GetAxis("Vertical"); // smoothed, -1..+1
Vector2 move = new Vector2(x, y);
move = Vector2.ClampMagnitude(move, 1f); // prevent diagonal speed boost
```
* Use `GetAxisRaw` for responsive arcade movement; `GetAxis` for smooth
camera-style axes.
* Always clamp the magnitude of a 2-axis vector -- otherwise diagonal
movement is ~1.41x faster than cardinal.
### Keys and buttons
```csharp
if (Input.GetKeyDown(KeyCode.Space)) Jump();
if (Input.GetKey(KeyCode.LeftShift)) Sprint();
if (Input.GetKeyUp(KeyCode.E)) Interact();
if (Input.GetMouseButtonDown(0)) Fire();
if (Input.GetMouseButton(0)) FireContinuous();
```
| Method | Fires when |
|-----------------------|-------------------------------------------|
| `GetKey` | Every frame the key is held |
| `GetKeyDown` | Only on the frame the key was pressed |
| `GetKeyUp` | Only on the frame the key was released |
| `GetMouseButton` | Every frame the button is held |
| `GetMouseButtonDown` | Only on the frame the button went down |
### Mouse position and delta
```csharp
Vector3 mousePos = Input.mousePosition; // screen-space pixels
float dx = Input.GetAxis("Mouse X"); // smoothed delta
float rawDx = Input.GetAxisRaw("Mouse X");
```
To lock the cursor for first-person look:
```csharp
Cursor.lockState = CursorLockMode.Locked; // hide + center
Cursor.visible = false;
```
## Mouse-look recipe (first-person)
```csharp
private float _pitch;
private void Update()
{
float mx = Input.GetAxisRaw("Mouse X") * sensitivity;
float my = Input.GetAxisRaw("Mouse Y") * sensitivity;
transform.Rotate(Vector3.up * mx);
_pitch = Mathf.Clamp(_pitch - my, -85f, 85f);
cameraTransform.localRotation = Quaternion.Euler(_pitch, 0f, 0f);
}
```
## Mouse-look recipe (third-person orbit)
For a third-person camera we accumulate a **yaw** and **pitch** and build a
rotation each frame:
```csharp
_yaw += Input.GetAxis("Mouse X") * sensitivity;
_pitch -= Input.GetAxis("Mouse Y") * sensitivity;
_pitch = Mathf.Clamp(_pitch, -30f, 75f);
Quaternion rotation = Quaternion.Euler(_pitch, _yaw, 0f);
Vector3 position = pivot + rotation * new Vector3(0f, height, -distance);
```
The `ThirdPersonCamera.cs` generator follows exactly this pattern.
## Input System package (new)
When the project has the Input System package active, the legacy `Input`
class will throw or return zeros unless `Project Settings > Player > Active Input Handling = Both`.
The new API is event-based:
```csharp
[SerializeField] private InputActionAsset actions;
private InputAction _moveAction;
private void OnEnable()
{
_moveAction = actions.FindAction("Move");
_moveAction.performed += OnMove;
_moveAction.Enable();
}
private void OnMove(InputAction.CallbackContext ctx) => _moveInput = ctx.ReadValue<Vector2>();
private void OnDisable() => _moveAction.Disable();
```
For the generated project we keep Active Input Handling on **Both** so the
legacy `Input` calls in the generated scripts keep working.
## Touch and mobile
For mobile, read `Input.touches` (legacy) or the new Input System's
`Pointer`/`Touchscreen`:
```csharp
foreach (Touch t in Input.touches)
{
if (t.phase == TouchPhase.Began) HandleTap(t.position);
}
```
The generated scripts are desktop-first; you would add a virtual joystick
overlay for mobile ports.
## Common pitfalls
* Reading `Input` in `FixedUpdate` -- the input system updates once per
frame, but `FixedUpdate` may run 0..N times per frame, so you will drop
or duplicate inputs.
* Using `Input.GetAxis` for physics forces -- the smoothed value can cause
floaty controls. Prefer `GetAxisRaw` and apply your own smoothing.
* Forgetting to lock the cursor in an FPS leads to the camera spinning
when the cursor leaves the game window.
|