S&box Wiki

Revision Difference

Input_System#548270

<cat>Code.Input</cat> <title>Input System</title> Input is part of [The Game Loop](GameLoop), 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. ⤶ # Building Input⤶ ⤶ Every frame `BuildInput( InputBuilder )` gets called clientside. [InputBuilder](Sandbox.InputBuilder) consists of inputs and outputs that are sent to the server such as InputBuilder.ViewAngles. Input is part of [The Game Loop](https://wiki.facepunch.com/sbox/GameLoop), 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](https://wiki.facepunch.com/sbox/Pawn) with the `[ClientInput]` attribute. Properties with this attribute are automatically serialized and sent to the server in a Command each tick. Before [Simulate](https://wiki.facepunch.com/sbox/GameLoop#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⤶ ⤶ ## Building Input⤶ ⤶ Every frame `BuildInput()` gets called clientside. The `Input` class can be used to grab raw input data and then use that data to set any properties with the `[ClientInput]` attribute.⤶ ```csharp // This could be overriding within a Game, Entity or Camera class. ⤶ public override void BuildInput( InputBuilder inputBuilder ) // 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()⤶ { // Only set new view angles if right mouse is held⤶ if ( inputBuilder.Down( InputButton.SecondaryAttack ) ) { inputBuilder.ViewAngles += inputBuilder.AnalogLook; inputBuilder.InputDirection = inputBuilder.AnalogMove; }⤶ InputDirection = Input.AnalogMove;⤶ ⤶ var look = Input.AnalogLook; ⤶ var viewAngles = ViewAngles; viewAngles += look; ViewAngles = viewAngles.Normal; } ``` ⤶ <warning>You should not use the static class Input within BuildInput, everything should be from the InputBuilder.</warning>⤶ ⤶ # Using Input⤶ ⤶ After the input is built the values are passed to the Input class both serverside and clientside. [Input](Sandbox.Input) can be used anywhere clientside, however serverside it can only be used in Simulate( Client ).⤶ ## Simulate Every tick client's send a **Command** that contains the values constructed from BuildInput. This command then gets simulated in [Game.Simulate( Client )](Sandbox.GameBase.Simulate) for each client. 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](Sandbox.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](Prediction). ```csharp // This could be overriding within a Game, Entity or Camera class. // 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.⤶ ⤶ ```csharp⤶ [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 ( Input.Pressed( InputButton.Jump ) ) { Velocity += Vector3.Up * 100.0f; } if ( Jump.Pressed ) { Velocity += Vector3.Up * 100f; } } ``` ⤶ # Keys with InputButton ⤶ ## 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 ⤶ ### 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 | | <note>You should rely on what the action actually does rather then binding to any specific keys.</note> ⤶ ## 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. ⤶ ### 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. ```csharp string useButton = Input.GetButtonOrigin( InputButton.Use ); ```