Code/Components/Car.cs
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RacingGame;
[Category( "Racing Game" )]
[Title( "Car" )]
[Icon( "directions_car" )]
public sealed class Car : Component
{
[RequireComponent] public Rigidbody Rigidbody { get; set; }
[Property, Group( "Vehicle" )] public float Torque { get; set; } = 15000f;
[Property, Group( "Vehicle" )] public float AccelerationRate { get; set; } = 1.0f;
[Property, Group( "Vehicle" )] public float DecelerationRate { get; set; } = 0.5f;
[Property, Group( "Vehicle" )] public float BrakingRate { get; set; } = 2.0f;
[Property] public GameObject CameraTarget { get; set; }
[Property] public float TerminalVelocity { get; set; } = 1000f;
[Property, Group( "Controls" )] public bool CanMove { get; set; } = false;
[Property, Group( "Controls" )] public bool IsLocked { get; set; } = false;
private List<Wheel> _wheels;
private static List<Car> All { get; } = new();
public static Car Local => All.FirstOrDefault( x => !x.Network.IsProxy );
protected override void OnEnabled()
{
All.Add( this );
_wheels = Components.GetAll<Wheel>( FindMode.EverythingInSelfAndDescendants ).ToList();
}
protected override void OnDisabled()
{
All.Remove( this );
}
private float _currentTorque;
protected override void OnFixedUpdate()
{
if ( IsProxy )
return;
float verticalInput = Input.AnalogMove.x;
float targetTorque = verticalInput * Torque;
if (!CanMove)
{
verticalInput = 0f;
targetTorque = 0f;
}
bool isBraking = Math.Sign( verticalInput * _currentTorque ) == -1;
bool isDecelerating = verticalInput == 0;
float lerpRate = AccelerationRate;
if ( isBraking )
lerpRate = BrakingRate;
else if ( isDecelerating )
lerpRate = DecelerationRate;
_currentTorque = _currentTorque.LerpTo( targetTorque, lerpRate * Time.Delta );
foreach ( Wheel wheel in _wheels )
{
wheel.ApplyMotorTorque( _currentTorque );
}
var groundVel = Rigidbody.Velocity.WithZ( 0f );
if ( verticalInput == 0f && groundVel.Length < 32f )
{
var z = Rigidbody.Velocity.z;
Rigidbody.Velocity = Vector3.Zero.WithZ( z );
}
if (Rigidbody.Velocity.Length > TerminalVelocity)
{
Rigidbody.Velocity = Rigidbody.Velocity.Normal * TerminalVelocity;
}
}
}