using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Playables;

public class AudioCrossfadePlayable : PlayableBehaviour
{
    Playable m_mixer;
    int m_inputCount;

    int m_fadeInIndex = 0;
    float m_fadeDuration = 0;

    public int CurrentIndex
    {
        get { return m_fadeInIndex; }
    }

    public float FadeDuration
    {
        get { return m_fadeDuration; }
    }

    public AudioCrossfadePlayable()
    {
    }

    public static ScriptPlayable<AudioCrossfadePlayable> Create(PlayableGraph graph, AudioMixerPlayable inputMixer)
    {
        var result = ScriptPlayable<AudioCrossfadePlayable>.Create(graph, 1);
        result.ConnectInput(0, inputMixer, 0, 1.0f);
        result.SetPropagateSetTime(true);

        var behaviour = result.GetBehaviour();
        behaviour.m_mixer = inputMixer;
        behaviour.m_inputCount = inputMixer.GetInputCount();
        return result;
    }

    public void Crossfade(int inputIndex, float fadeDuration)
    {
        if (fadeDuration == 0)
        {
            Switch(inputIndex);
        }
        else
        {
            if (inputIndex >= 0 && m_mixer.GetInputWeight(inputIndex) == 0)
            {
                // Start clip from beginning
                m_mixer.GetInput(inputIndex).SetTime(0);
            }
            m_fadeInIndex = inputIndex;
            m_fadeDuration = fadeDuration;
        }
    }

    public void Switch(int inputIndex)
    {
        m_fadeInIndex = -1;
        m_fadeDuration = 0;
        for (int i = 0; i < m_inputCount; i++)
        {
            m_mixer.SetInputWeight(i, i == inputIndex ? 1 : 0);
        }
        if (inputIndex >= 0)
        {
            // Start clip from beginning
            m_mixer.GetInput(inputIndex).SetTime(0);
        }
    }

    public override void PrepareFrame(Playable playable, FrameData info)
    {
        if (m_fadeDuration > 0)
        {
            bool fadeInProgress = false;
            float delta = info.deltaTime / m_fadeDuration;

            for (int i = 0; i < m_inputCount; i++)
            {
                float weight = m_mixer.GetInputWeight(i);
                if (m_fadeInIndex == i)
                {
                    if (weight < 1)
                    {
                        // Sqrt fade in
                        weight = weight * weight;
                        weight = Math.Min(weight + delta, 1);
                        weight = Mathf.Sqrt(weight);
                        m_mixer.SetInputWeight(i, weight);
                        fadeInProgress = true;
                    }
                }
                else if (weight > 0)
                {
                    // Sq fade out
                    weight = Mathf.Sqrt(weight);
                    weight = Math.Max(weight - delta, 0);
                    weight = weight * weight;
                    m_mixer.SetInputWeight(i, weight);
                    fadeInProgress = true;
                }
            }

            if (!fadeInProgress)
            {
                m_fadeDuration = 0;
            }
        }

        if (m_fadeDuration == 0 && m_fadeInIndex == -1)
        {
            playable.GetGraph().Stop();
        }
    }
}

Add a code snippet to your website: www.paste.org