For the complete documentation index, see llms.txt. This page is also available as Markdown.

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 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 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 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 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 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 we bind input from Unity's Legacy Input Manager to Reactor input with the following script:

To do the same thing with Unity's newer Input System Package, 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'.

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.

Last updated