Component that reads player or bot input for a vehicle and syncs it to clients. It handles controller vs keyboard input, applies game-state gating (steer-only mode, spinout), and uses a RacingBrain for bot input.
using Machines.GameModes;
namespace Machines.Player;
/// <summary>
/// Reads and syncs player input; remotes read it for visual effects
/// </summary>
public sealed class CarInput : Component
{
[RequireComponent]
public Car Car { get; private set; }
/// <summary>
/// Current input state, synced to all clients.
/// </summary>
[Sync]
public CarInputData Current { get; private set; }
/// <summary>
/// When true, only steering is read; throttle/boost/drift suppressed
/// </summary>
private bool _steerOnly;
protected override void OnUpdate()
{
_steerOnly = BaseGameMode.Current.IsValid() && BaseGameMode.Current.State != GameModeState.Playing;
// While spun out the car accepts no input at all
if ( Car.Spinout.IsValid() && Car.Spinout.IsSpinning )
{
Current = default;
return;
}
if ( Car.IsBot || Car.Autopilot )
{
var brain = GetOrAddComponent<RacingBrain>();
if ( brain.IsValid() )
{
var botData = brain.Tick();
if ( _steerOnly )
{
botData = new CarInputData { Steer = botData.Steer };
}
Current = botData;
}
return;
}
if ( !Car.IsLocalPlayer )
return;
ReadInput();
}
protected override void OnDisabled()
{
Current = default;
}
private void ReadInput()
{
var data = new CarInputData();
if ( Input.UsingController )
{
var gas = Input.GetAnalog( InputAnalog.RightTrigger );
var brake = Input.GetAnalog( InputAnalog.LeftTrigger );
data.Throttle = gas - brake;
// Stick steering relative to the car
var stick = Input.AnalogMove;
if ( stick.Length > 0.1f && Car.Movement.IsValid() )
{
data.Steer = Input.AnalogMove.y;
}
}
else
{
var move = Input.AnalogMove;
data.Throttle = move.x;
data.Steer = move.y;
}
data.Drift = Input.Down( "Drift" );
data.Boost = Input.Down( "Boost" );
data.UseItem = Input.Down( "UseItem" );
if ( _steerOnly )
{
data.Throttle = 0f;
data.Drift = false;
data.Boost = false;
data.UseItem = false;
}
Current = data;
}
}