> For the complete documentation index, see [llms.txt](https://kinematicsoup.gitbook.io/reactor/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kinematicsoup.gitbook.io/reactor/examples/input_manager.md).

# Managing Input

#### Input

### Summary

The input manager is used to convert input from Unity to Reactor input that is sent over the network and processed on the server in a player controller. Processing inputs on the server makes it more difficult to cheat and enables complex physics-based interactions. In [Tutorial 2](/reactor/tutorials/player_controllers.md) we used the input manager to bind input from Unity's legacy Input Manager to Reactor input. This example shows how to convert input from Unity's newer [Input System Package](https://docs.unity3d.com/Packages/com.unity.inputsystem@latest/) or other sources to Reactor input. It also shows how inputs can be disabled, which can be used to disable input when the player is in a menu.

#### Types of Input

Reactor has 3 kinds of input: buttons, axes, and values. Each button, axes, and value is identified by a uint id that you define.

* A **Button** can be either up or down. You can check if it is down or up using `Input.IsDown(buttonId)`. You can checked if it's state changed from up to down on this update using `Input.IsPressed(buttonId)`, or if it changed from down to up using `Input.IsReleased(buttonId)`.
* An **Axis** is a float in the range \[-1, 1]. You can get the value of the float using `Input.GetAxis(axisId)`.
* A **Value** is a *ksMultiType*, a struct-union type that can hold most primitive types and some structs such as *ksVector3* and *ksColor*. See [Tutorial 4](/reactor/tutorials/properties_and_rpcs.md) for the full list of supported types. You can get a value using `Input.GetValue(valueId)`. If the value is not set, it will return `ksMultiType.NULL`.

Inputs are only sent to the server for players that have a [player controller](/reactor/tutorials/player_controllers.md) attached to an entity. All inputs you are using must be registered in the player controller `RegisterInputs(registrar)` function, or they will not be sent.

```
using KS.Reactor;

// Ids for axes inputs
public class Axes
{
    public const uint X = 0;
    public const uint Y = 1;
}

// Ids for button inputs
public class Buttons
{
    public const uint JUMP = 0;
    public const uint SHOOT = 1;
}

// Ids for value inputs
public class Values
{
    public const uint AIM = 0;
}

public PlayerController : ksPlayerController
{
    // Unique non-zero identifier for this player controller class.
    public override uint Type
    {
        get { return 1; }
    }

    // Register all buttons, axes, and values you will be using here.
    public override void RegisterInputs(ksInputRegistrar registrar)
    {
        registrar.RegisterAxes(Axes.X, Axes.Y);
        registrar.RegisterButtons(Buttons.JUMP, Buttons.SHOOT);
        registrar.RegisterValues(Values.AIM);
    }
    
    // Called during the update cycle.
    public override void Update()
    {
        // Add code to move the character using inputs here.
    }
}
```

#### Input Settings

*ksRoom* has the following settings related to input:

* **InputInterval** The interval in seconds at which input updates are generated and sent to the server. Defaults to 60 per second. If 0, one input update will be generated for every client frame. This is not recommended if your game has an uncapped frame rate and you could send inputs faster than the server processes them, causing the input lag and dropped inputs. Setting to less than zero disables automatic input update generation, allowing you to manually control when input updates are generated by calling `Room.SendInput(sendUnchanged, deltaTime)`.
* **SendUnchangedInput** - If false, Reactor will not send an input update if no inputs have changed since the last input update. Unless you are using a custom [Input Processor](/reactor/examples/input_processors.md) that requires every input update to be sent, you should leave this false.
* **MultiButtonStateEnabled** - Because the client frame rate may be faster than the input interval, multiple client frames may be combined into one input update. It is possible a button may have changed it's up/down state multiple times in the same input update. If that happens and this setting is true, both `Input.IsPressed(button)` and `Input.IsReleased(button)` will return true on the same update for that button. If this setting is false, the button can only change it's up/down state once per input update. Defaults to false.

#### Using Input from the Unity Input System Package and Other Sources

In [Tutorial 2](/reactor/tutorials/player_controllers.md) we bind input from Unity's Legacy Input Manager to Reactor input with the following script:

```c#
using System.Collections.Generic;
using UnityEngine;
using KS.Reactor;
using KS.Reactor.Client.Unity;

// Bind inputs with Reactor
public class BindInputs : MonoBehaviour
{
    // Run when the game starts.
    void Start()
    {
        // Bind Unity input to Reactor input.
        ksReactor.InputManager.BindAxis(Axes.X, "Horizontal");
        ksReactor.InputManager.BindAxis(Axes.Y, "Vertical");
        ksReactor.InputManager.BindButton(Buttons.JUMP, "Jump");
    }
}
```

To do the same thing with Unity's newer [Input System Package](https://docs.unity3d.com/Packages/com.unity.inputsystem@latest/), we will instead create a client room script that polls the move and jump actions in `Update` and sets the Reactor axes and buttons. `Axes` and `Buttons` are classes containing const uints defined in another file. This script works with the default project-wide actions that are created for you when you click the **'Create and assign a default project-wide Action Asset'** button when you go to **'Edit->Project Settings->Input System Package'**.

```c#
using UnityEngine;
using UnityEngine.InputSystem;
using KS.Reactor.Client.Unity;

public class crInput : ksRoomScript
{
    private InputAction m_move;
    private InputAction m_jump;

    // Called after all other scripts/entities are attached/spawned.
    public override void Initialize()
    {
        m_move = InputSystem.actions.FindAction("Move");
        m_jump = InputSystem.actions.FindAction("Jump");
    }
    
    // Called every frame.
    private void Update()
    {
        if (m_move != null)
        {
            Vector2 moveInput = m_move.ReadValue<Vector2>();
            ksReactor.InputManager.SetAxis(Axes.X, moveInput.x);
            ksReactor.InputManager.SetAxis(Axes.Y, moveInput.y);
        }
        if (m_jump != null)
        {
            ksReactor.InputManager.SetButton(Buttons.JUMP, m_jump.IsPressed());
        }
    }
}
```

If you bind an axis to the legacy Unity Input Manager and also set the value directly using `ksReactor.InputManager.SetAxes(axisId, value)`, the value used will be whichever of yours of Unity's has a higher absolute value.

If you bind a button to the legacy Unity Input Manager and also set the button state directly using `ksReactor.SetButton(buttonId, value)`, the button will be down if either you or Unity set it to down.

Input values cannot be bound directly to Unity's legacy Input Manager. Instead they can be bound to a delegate. In the above example we could combine the X and Y axes into a single *ksVector2* value and bind it using `ksReactor.InputManager.BindValue(Values.MOVE, () => m_move.ReadValue<Vector2>())`, or we could set it in `Update` using `ksReactor.InputManager.SetValue(Values.MOVE, m_move.ReadValue<Vector2>())`.

#### Disabling Inputs

You can disable all inputs by setting `ksReactor.InputManager.Enabled = false;`. When inputs are disabled, all axes will be 0, all buttons will be up, and all values will be `ksMultiType.NULL`. You can use this to stop the player from moving while they have a menu open.

When you bind a button to the legacy Unity Input Manager, you can bind it with a validator function. The validator function is called each time the button is pressed. If it returns false, the button will stay up for the duration of that button press. You can use this to ignore button pressed when the user is typing in an input field. The following example shows how to prevent button presses when any *TMP\_InputField* is focused.

```c#
using UnityEngine;
using KS.Reactor.Client.Unity;
using TMPro;
using UnityEngine.EventSystems;

public class BindInputs : MonoBehaviour
{
    // Start is called before the first frame update
    private void Start()
    {
        // Bind the jump button with a validator that prevents button presses when inputs are focused
        ksReactor.InputManager.BindButton(Buttons.JUMP, "Jump", NoInputsFocused);
    }

    // Returns false if any TMP_InputFields are focused
    private bool NoInputsFocused()
    {
        // Get the object currently selected by the EventSystem
        GameObject currentObj = EventSystem.current.currentSelectedGameObject;

        // Check if it exists and has a TMP_InputField component
        return currentObj == null || currentObj.GetComponent<TMP_InputField>() == null;
    }
}
```
