Components/BoostPad.cs

A scene component that acts as a boost pad. When a car enters its trigger it applies a forward impulse to the car's Movement component and enforces a per-car cooldown. It also draws editor gizmos showing direction and area.

Native Interop
using Machines.Player;

namespace Machines.Track;

/// <summary>
/// Applies a forward impulse to any car that drives over it. Place on a trigger collider.
/// </summary>
public sealed class BoostPad : Component, Component.ITriggerListener
{
	/// <summary>
	/// Impulse strength applied in the pad's forward direction (units/s).
	/// </summary>
	[Property]
	public float BoostStrength { get; set; } = 400f;

	/// <summary>
	/// Per-car cooldown in seconds before it can be boosted again.
	/// </summary>
	[Property]
	public float Cooldown { get; set; } = 2f;

	private readonly Dictionary<int, float> _cooldowns = new();

	public void OnTriggerEnter( Collider other )
	{
		var car = other.GameObject.GetComponentInParent<Car>();
		if ( !car.IsValid() || !car.Movement.IsValid() )
			return;

		var id = car.GameObject.Id.GetHashCode();
		if ( _cooldowns.TryGetValue( id, out var nextTime ) && Time.Now < nextTime )
			return;

		_cooldowns[id] = Time.Now + Cooldown;

		var boostDir = WorldRotation.Forward;
		car.Movement.ApplyImpulse( boostDir * BoostStrength, gripSuppressSeconds: 0.3f );
	}

	public void OnTriggerExit( Collider other ) { }

	protected override void DrawGizmos()
	{
		Gizmo.Draw.Color = Color.Orange.WithAlpha( 0.7f );
		Gizmo.Draw.Arrow( Vector3.Zero, Vector3.Forward * 40f, 8f, 4f );

		Gizmo.Draw.Color = Color.Orange.WithAlpha( 0.3f );
		Gizmo.Draw.LineBBox( BBox.FromPositionAndSize( Vector3.Zero, new Vector3( 60f, 60f, 10f ) ) );
	}
}