Helper/SkateAudioHelper.cs
using System;

namespace Skateboard.Player;

public sealed class SkateAudioHelper : Component
{
	[Property] public SkatePawn Pawn { get; set; }

	[Property] private SoundEvent RollSound { get; set; }

	SoundHandle rollSound;

	private bool PreviouslyOnGround;

	protected override void OnUpdate()
	{
		var pawn = Pawn ?? Components.Get<SkatePawn>();
		if ( pawn is null )
			return;

		if ( !IsLocallyControlled( pawn ) )
			return;

		var pawnVelocity = pawn.Velocity.Length;
		var grounded = pawn.Controller?.IsGrounded ?? false;


		if ( !grounded || pawn.Bailed )
		{
			if ( rollSound.IsValid() )
				rollSound.Stop();
			PreviouslyOnGround = false;
			return;
		}

		if ( !PreviouslyOnGround || !rollSound.IsValid() )
		{
			if ( rollSound.IsValid() )
				rollSound.Stop();
			rollSound = pawn.GameObject.PlaySound( RollSound );
		}

		if ( rollSound.IsValid() )
		{
			rollSound.Volume = pawnVelocity * 0.005f;
			rollSound.Pitch = Math.Min( 1.5f, Math.Max( 0.5f, pawnVelocity * 0.0009f ) );
		}

		PreviouslyOnGround = true;
	}

	private static SoundHandle PlayPawnSound( GameObject target, string eventName )
	{
		var soundEvent = ResourceLibrary.Get<SoundEvent>( eventName );
		return target.PlaySound( soundEvent );
	}

	private static bool IsLocallyControlled( SkatePawn pawn )
	{
		if ( !Networking.IsActive )
			return true;

		if ( pawn.GameObject.Network.IsOwner )
			return true;

		return pawn.OwningConnectionId == Connection.Local.Id;
	}
}