S&box Wiki

Input System

Input is part of The Game Loop, every frame our clients build their input, converting your mouse, keyboard and controller inputs into a Command that is sent to the server each tick.

Client Input Properties

You can mark properties on a Pawn or Entity Component attached to a Pawn with the [ClientInput] attribute. Properties with this attribute are automatically serialized and sent to the server in a Command each tick. Before Simulate is called on the client and server these properties are reset to the correct values from the Command.

Supported Types

  • float
  • int
  • bool
  • string
  • Vector2
  • Vector3
  • Rotation
  • Angles
  • Transform
  • Entity
  • ButtonState

Help, I'm Upgrading

If you are currently transitioning from the old way of doing things to the new way, here are some pointers:

Input.Rotation is gone. In most cases this isn't really needed for games that aren't an FPS. You can implement your own version of this (see Building Input for a view angles implementation example).

Input.Forward and Input.Left are gone. These values are basically just Input.AnalogMove.x and Input.AnalogMove.y respectively, so there's no need to have them.

Examples

You can checkout the Sandbox gamemode to see how it has been upgraded to this system. Examples include ActiveChild, InputDirection and ViewAngles.

Building Input

Every frame BuildInput() gets called clientside. The static Input class can be used to grab raw input data and then use that data to set any properties with the [ClientInput] attribute.

// An example BuildInput method within a player's Pawn class. [ClientInput] public Vector3 InputDirection { get; protected set; } [ClientInput] public Angles ViewAngles { get; set; } public override void BuildInput() { InputDirection = Input.AnalogMove; var look = Input.AnalogLook; var viewAngles = ViewAngles; viewAngles += look; ViewAngles = viewAngles.Normal; }

Simulate

Every tick clients send a Command that contains the values constructed from BuildInput. This command then gets simulated in Game.Simulate( Client ) for each client.

Within Simulate( Client ) the static Input class contains inputs specific to the currently simulated client, this allows you to run the same code on both the server and client for Prediction.

// An example Simulate method within a player's Pawn class. public override void Simulate( Client cl ) { if ( Input.Pressed( InputButton.Jump ) ) { Velocity += Vector3.Up * 100f; } Velocity += InputDirection * 400f; Rotation = ViewAngles.ToRotation(); }

Button State

A [ClientInput] property can also be a ButtonState. This struct lets you treat an input as if it were a button, so that in Simulate you can get whether it was "pressed" or "released" or whether it is "down". This can make stuff like couch co-op easier.

[ClientInput] public ButtonState Jump { get; set; } public override void BuildInputs() { if ( IsPlayerOne ) Jump = Input.Down( InputButton.Jump ); else if ( IsPlayerTwo ) Jump = Input.Down( InputButton.Drop ); } public override void Simulate( Client client ) { if ( Jump.Pressed ) { Velocity += Vector3.Up * 100f; } }

Keys with InputButton

s&box does not provide raw access to the user's keyboard, instead there is a set of standard bindings your game can make use of.

Default Bindings

InputButton Binding Default Controller Default
InputButton.Forward +iv_forward W Unbound ( Analog )
InputButton.Back +iv_back S Unbound ( Analog )
InputButton.Left +iv_left A Unbound ( Analog )
InputButton.Right +iv_right D Unbound ( Analog )
InputButton.Jump +iv_jump Space A
InputButton.Duck +iv_duck Ctrl B
InputButton.Run +iv_sprint Shift Left Stick Press
InputButton.Walk +iv_walk Alt Unbound
InputButton.PrimaryAttack +iv_attack Mouse1 RT ( Soft press )
InputButton.SecondaryAttack +iv_attack2 Mouse2 LT ( Soft press )
InputButton.Reload +iv_reload R X
InputButton.Grenade +iv_grenade
InputButton.Drop +iv_drop G
InputButton.Use +iv_use E Y
InputButton.Flashlight +iv_flashlight F DPAD UP
InputButton.View +iv_view C Right Stick Press
InputButton.Zoom +iv_zoom Mouse3 Unbound
InputButton.Menu +iv_menu Q Pause Button
InputButton.Score +iv_score Tab Back Button
InputButton.Chat ?
InputButton.Voice +iv_voice V
InputButton.SlotNext +iv_slotnext RB
InputButton.SlotPrev +iv_slotprev LB
InputButton.Slot1 +iv_slot1 1 DPAD LEFT
InputButton.Slot2 +iv_slot2 2 DPAD RIGHT
InputButton.Slot3 +iv_slot3 3 DPAD DOWN
InputButton.Slot4 +iv_slot4 4
InputButton.Slot5 +iv_slot5 5
InputButton.Slot6 +iv_slot6 6
InputButton.Slot7 +iv_slot7 7
InputButton.Slot8 +iv_slot8 8
InputButton.Slot9 +iv_slot9 9
InputButton.Slot0 +iv_slot0 0
You should rely on what the action actually does rather then binding to any specific keys.

Getting Bound Keys

You can get the key the user has bound to a button with Input.GetButtonOrigin( InputButton ), this can be used to prompt the user what key or controller button to press.

string useButton = Input.GetButtonOrigin( InputButton.Use );