2

不幸的是,我制作的这个音频衰减功能遇到了障碍。它包含一个源、持续时间和一个新剪辑。它应该淡出初始剪辑,替换剪辑并将音量恢复到 1。

public static IEnumerator FadeSwitchAudio(AudioSource audioSource, float duration, int clip)
{
    float firstTimer = 0;
    float secondTimer = 0;
    float start = audioSource.volume;

    // Fade audio out, works as intended 
    while (firstTimer < duration)
    {
        firstTimer += Time.deltaTime;
        audioSource.volume = Mathf.Lerp(start, 0.01f, firstTimer / duration);
        yield return null;
    }

    audioSource.clip = GameObject.FindWithTag("AudioManager").GetComponent<AudioManager>().clips[clip];

    // Fade audio back in, volume jumps immediately to 1 and audiosource stops having output
    yield return new WaitForSeconds(0.1f);
    while (secondTimer < duration)
    {
        secondTimer += Time.deltaTime;
        audioSource.volume = Mathf.Lerp(start, 1.0f, secondTimer / duration);
        yield return null;
    }
}

我尝试了很多不同的计时器功能,但是,增加音频源的音量似乎总是会破坏它。是否有可靠的方法可以在不完全丢失输出的情况下缓慢增加源的音频?这是检查器中当前行为的 gif。请原谅低分辨率,但你可以看到行为。

Unity Audio Lerping 问题

感谢您的时间!

4

1 回答 1

1

这里有两个问题:

  • 只改变AudioSource.clip不做任何事情。

    使用新音频剪辑分配剪辑不会立即更改正在播放的剪辑

    您还需要使用AudioSource.Play.

  • 同样作为start第二个循环的新循环,您不想使用AudioSource.volume存储在 Corouinte 顶部的原始循环,而是使用淡出后的当前循环。

所以只是稍微修改一下,我会使用例如

private const float FADED_OUT_VOLUME = 0.01f;

public static IEnumerator FadeSwitchAudio(AudioSource audioSource, float duration, int clip)
{
    var originalVolume = audioSource.volume;

    // I prefer using for loops over while to eliminate the danger of infinite loops
    // and the need for "external" variables
    // I personally also find this better to read and maintain
    for(var timePassed = 0f; timePassed < duration; timePassed += Time.deltaTime)
    {
        audioSource.volume = Mathf.Lerp(originalVolume, FADED_OUT_VOLUME, timePassed / duration);

        yield return null;
    }

    // To be sure to end with clean values
    audioSource.volume = FADED_OUT_VOLUME;

    // If there is only one instance of `AudioManager` in your scene this is more efficient
    // in general you should fetch that AudioManager reference only ONCE and re-use it
    audioSource.clip = FindObjectOfType<AudioManager>().clips[clip];
    //audioSource.clip = GameObject.FindWithTag("AudioManager").GetComponent<AudioManager>().clips[clip];

    yield return new WaitForSeconds(0.1f);

    // Actually start playing the new clip
    audioSource.Play();

    for(var timePassed = 0f; timePassed < duration; timePassed += Time.deltaTime)
    {
        audioSource.volume = Mathf.Lerp(FADED_OUT_VOLUME, originalVolume, timePassed / duration);

        yield return null;
    }

    audioSource.volume = 1f;
}
于 2021-08-10T06:31:33.947 回答