public class PlayerController : MonoBehaviour
{
[SerializeField] AudioClip jumpClip;
[SerializeField] float jumpVolume = 1f;
[SerializeField] float minPitch = 0.9f;
[SerializeField] float maxPitch = 1.1f;
[SerializeField] float fadeInDuration = 0.5f;
[SerializeField] float fadeOutDuration = 0.3f;
AudioSource jumpSource;
Coroutine activeFadeCoroutine;
bool isFadingOut;
void Awake()
{
jumpSource = GetComponent<AudioSource>();
if (jumpSource == null)
jumpSource = gameObject.AddComponent<AudioSource>();
jumpSource.playOnAwake = false;
jumpSource.loop = false;
jumpSource.spatialBlend = 0f;
jumpSource.volume = jumpVolume;
}
void OnDisable()
{
CancelActiveFade();
}
void OnJump()
{
PlayJumpSoundWithRandomPitchAndFadeIn();
}
void OnLand()
{
FadeOutJumpSound();
}
void PlayJumpSoundWithRandomPitchAndFadeIn()
{
if (jumpClip == null)
return;
if (jumpSource == null)
return;
CancelActiveFade();
isFadingOut = false;
jumpSource.Stop();
jumpSource.clip = jumpClip;
jumpSource.pitch = Random.Range(minPitch, maxPitch);
jumpSource.volume = 0f;
jumpSource.Play();
if (fadeInDuration <= 0f)
{
jumpSource.volume = jumpVolume;
return;
}
activeFadeCoroutine = StartCoroutine(FadeJumpVolumeIn());
}
void FadeOutJumpSound()
{
if (jumpSource == null)
return;
if (jumpClip == null)
return;
if (!jumpSource.isPlaying && !isFadingOut)
return;
CancelActiveFade();
isFadingOut = true;
if (fadeOutDuration <= 0f)
{
jumpSource.Stop();
jumpSource.volume = jumpVolume;
jumpSource.pitch = 1f;
isFadingOut = false;
return;
}
activeFadeCoroutine = StartCoroutine(FadeJumpVolumeOut());
}
void StopJumpSound()
{
CancelActiveFade();
isFadingOut = false;
if (jumpSource == null)
return;
jumpSource.Stop();
jumpSource.volume = jumpVolume;
jumpSource.pitch = 1f;
}
void CancelActiveFade()
{
if (activeFadeCoroutine == null)
return;
StopCoroutine(activeFadeCoroutine);
activeFadeCoroutine = null;
}
IEnumerator FadeJumpVolumeIn()
{
float elapsed = 0f;
float startVolume = jumpSource.volume;
float targetVolume = jumpVolume;
while (elapsed < fadeInDuration)
{
if (jumpSource == null)
yield break;
if (isFadingOut)
yield break;
elapsed += Time.deltaTime;
jumpSource.volume = Mathf.Lerp(
startVolume,
targetVolume,
elapsed / fadeInDuration
);
yield return null;
}
if (jumpSource == null)
yield break;
jumpSource.volume = targetVolume;
activeFadeCoroutine = null;
}
IEnumerator FadeJumpVolumeOut()
{
float elapsed = 0f;
float startVolume = jumpSource.volume;
while (elapsed < fadeOutDuration)
{
if (jumpSource == null)
yield break;
elapsed += Time.deltaTime;
jumpSource.volume = Mathf.Lerp(
startVolume,
0f,
elapsed / fadeOutDuration
);
yield return null;
}
if (jumpSource == null)
yield break;
jumpSource.Stop();
jumpSource.volume = jumpVolume;
jumpSource.pitch = 1f;
isFadingOut = false;
activeFadeCoroutine = null;
}
}