IEnumerator FadeCoroutine(float targetOpacity, float duration = 1f)
    {
        isFading       = true;
        blocksRaycasts = true;
        Debug.Log("Fading!");
        FadeBegin.Invoke();
        float baseOpacity = opacity;
        float timer       = 0f;

        while (timer < duration)
        {
            timer  += Time.deltaTime;
            opacity = Mathf.Lerp(baseOpacity, targetOpacity, timer / duration);
            //Debug.Log("Current opacity: " + opacity);
            yield return(null);
        }

        // Make sure to be precise
        opacity = targetOpacity;

        fadeCoroutine = null;

        // Makes it so the screen doesn't keep you from interacting with UI elements
        // when it's done.
        blocksRaycasts = false;
        isFading       = false;
        FadeEnd.Invoke();
    }
    IEnumerator Fade(float targetVolume, float duration)
    {
        FadeStart.Invoke();
        float timer      = 0;
        float baseVolume = audioSource.volume;

        do
        {
            if (duration == 0)
            {
                audioSource.volume = targetVolume;
                FadeEnd.Invoke();
                yield break;
            }

            timer += Time.deltaTime;
            audioSource.volume = Mathf.Lerp(baseVolume, targetVolume, timer / duration);
            yield return(null);
        }while (timer <= duration);

        // In case the lerping makes timer go past duration.
        audioSource.volume = targetVolume;

        // Signify that the fading is done.
        fadeCoroutine = null;
        FadeEnd.Invoke();
    }
    void ResetState()
    {
        Debug.Log("ScreenFader state reset!");
        if (fadeCoroutine != null)
        {
            Debug.Log("Stopping fade cooroutine!");
            StopCoroutine(fadeCoroutine);
        }

        opacity = 0;
        FadeBegin.RemoveAllListeners();
        FadeEnd.RemoveAllListeners();
    }