コード例 #1
0
        //===========================================================================================

        /**
         *  @brief
         *
         *********************************************************************************************/
        private void AddClipToPreview(AnimationClip a_clip)
        {
            if (m_previewActive && a_clip != null)
            {
                m_blendWeights.Add(0f);

                AnimationMixerPlayable mixer = MxMPreviewScene.Mixer;

                int inputId = mixer.GetInputCount();
                mixer.SetInputCount(inputId + 1);

                var clipPlayable = AnimationClipPlayable.Create(MxMPreviewScene.PlayableGraph, a_clip);

                mixer.ConnectInput(inputId, clipPlayable, 0);

                for (int i = 0; i < mixer.GetInputCount(); ++i)
                {
                    var playable = mixer.GetInput(i);

                    if (playable.IsValid())
                    {
                        playable.SetTime(0f);
                    }
                }

                CalculateBlendWeights();
                ApplyBlendWeights();
            }
        }
コード例 #2
0
 public void ClearMainMixerInput()
 {
     for (int i = 0; i < mixer.GetInputCount(); i++)
     {
         mixer.GetInput(i).Destroy();
     }
     mixer.SetInputCount(0);
     asBuffor = null;
 }
コード例 #3
0
    public Playable GetInput(int index)
    {
        if (index >= m_Mixer.GetInputCount())
        {
            return(Playable.Null);
        }

        return(m_Mixer.GetInput(index));
    }
コード例 #4
0
    public override void PrepareFrame(Playable owner, FrameData info)
    {
        int ClipCount = m_mixerPlayable.GetInputCount();

        if (ClipCount == 0)
        {
            return;
        }

        m_timeToNextClip -= info.deltaTime;

        if (m_timeToNextClip <= 0.0f)
        {
            m_currentClipIndex++;
            if (m_currentClipIndex >= ClipCount)
            {
                m_currentClipIndex = 0;
            }
            var currentClip = (AnimationClipPlayable)m_mixerPlayable.GetInput(m_currentClipIndex);

            //SetTime(0),从头开始播放动画
            currentClip.SetTime(0);
            m_timeToNextClip = currentClip.GetAnimationClip().length;
        }

        //利用权重来设置当前播放的Clip
        for (int clipIndex = 0; clipIndex < ClipCount; ++clipIndex)
        {
            m_mixerPlayable.SetInputWeight(clipIndex, clipIndex == m_currentClipIndex ? 1 : 0);
        }
    }
コード例 #5
0
        public void PlayAnimation(Playable owner, AnimationClip clip)
        {
            var bindIndex = _clipData.FindIndex(cd => cd.Clip == clip);

            if (bindIndex == -1)
            {
                owner.Pause();
                return;
            }

            var data = _clipData[bindIndex];

            CurrentClipIndex = data.MixerIndex;

            var clipPlayable = (AnimationClipPlayable)Mixer.GetInput(CurrentClipIndex);

            clipPlayable.SetTime(0.0);

            var inputCount = Mixer.GetInputCount();

            for (var idx = 0; idx < inputCount; idx++)
            {
                Mixer.SetInputWeight(idx, idx != CurrentClipIndex ? 0.0f : 1.0f);
            }

            owner.Play();
        }
コード例 #6
0
        public static void RemoveZeroWeightsInputs(AnimationMixerPlayable mixer)
        {
            int size = mixer.GetInputCount();

            for (int i = 0; i < size; i++)
            {
                if (mixer.GetInputWeight(i) <= 0)
                {
                    mixer.GetInput(i).Destroy();
                    for (int j = i + 1; j < size; j++)
                    {
                        // double localTime = ((AnimationClipPlayable)mixer.GetInput(j)).GetTime();
                        float    _weight = mixer.GetInputWeight(j);
                        Playable clip    = mixer.GetInput(j);
                        // clip.SetTime(localTime);
                        mixer.DisconnectInput(j);
                        mixer.ConnectInput(j - 1, clip, 0);
                        mixer.SetInputWeight(j - 1, _weight);
                    }
                    i--;
                    size--;
                    mixer.SetInputCount(size);
                }
            }
        }
コード例 #7
0
        public void BlendPlayablesInStateMixer(
            ref AnimationMixerPlayable stateMixer,
            List <float> blendingSpeeds,
            List <float> currentWeights,
            float minWeightToAchive = 0f,
            float blendTime         = 0.5f
            )
        {
            int   size      = stateMixer.GetInputCount();
            float weightSum = 0;

            for (int i = 0; i < size; i++)
            {
                if (i < (size - 1) && minWeightToAchive <= currentWeights[i] && blendingSpeeds[i] > 0)
                {
                    blendingSpeeds[i] = -(currentWeights[i] / blendTime);
                }
                currentWeights[i] = Mathf.Clamp01(currentWeights[i] + (blendingSpeeds[i] * Time.deltaTime));
                weightSum        += currentWeights[i];
            }

            for (int i = 0; i < size; i++)
            {
                stateMixer.SetInputWeight(i, currentWeights[i] / weightSum);
            }
        }
コード例 #8
0
        //===========================================================================================

        /**
         *  @brief
         *
         *********************************************************************************************/
        public void EndPreviewLocal()
        {
            if (!m_previewActive)
            {
                return;
            }

            AnimationMixerPlayable mixer = MxMPreviewScene.Mixer;

            if (mixer.IsValid())
            {
                for (int i = 0; i < mixer.GetInputCount(); ++i)
                {
                    var clipPlayable = mixer.GetInput(0);

                    if (clipPlayable.IsValid())
                    {
                        mixer.DisconnectInput(0);
                        clipPlayable.Destroy();
                    }
                }
            }

            m_previewActive     = false;
            m_previewBlendSpace = null;
        }
コード例 #9
0
        public override void PrepareFrame(Playable playable, FrameData info)
        {
            if (mixer.GetInputCount() == 0)
            {
                return;
            }

            timeToNextClip -= info.deltaTime;

            if (timeToNextClip <= 0)
            {
                MoveToNextClip();
            }

            UpdateWeights();
        }
コード例 #10
0
        public void AddClipPlayable(
            AnimationMixerPlayable mixer,
            AnimationClip animation,
            bool passIK,
            bool passFootIK  = false,
            double localTime = 0d,
            float weight     = 0f
            )
        {
            AnimationClipPlayable playable = AnimationClipPlayable.Create(this.graph, animation);

            playable.SetApplyPlayableIK(passIK);
            playable.SetApplyFootIK(passFootIK);
            mixer.AddInput(playable, 0, weight);
            mixer.GetInput(mixer.GetInputCount() - 1).SetTime(localTime);
            mixer.GetInput(mixer.GetInputCount() - 1).SetTime(localTime);
        }
コード例 #11
0
    // Use this for initialization
    void Start()
    {
        animator = GetComponent <Animator>();

        playableGraph = PlayableGraph.Create("ClairePlayableGraph");
        playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
        var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", animator);

        // Create Top Level Layer Mixer
        AnimationLayerMixerPlayable mixerLayerPlayable = AnimationLayerMixerPlayable.Create(playableGraph, 2);

        playableOutput.SetSourcePlayable(mixerLayerPlayable);

        // Create an Emotion Mixer
        mixerEmotionPlayable = AnimationMixerPlayable.Create(playableGraph, 4);

        // Wrap AnimController
        runtimeAnimController = animator.runtimeAnimatorController;
        var runtimeAnimControllerPlayable = AnimatorControllerPlayable.Create(playableGraph, runtimeAnimController);

        // Connect to Top Level Layer Mixer
        playableGraph.Connect(runtimeAnimControllerPlayable, 0, mixerLayerPlayable, 0);
        playableGraph.Connect(mixerEmotionPlayable, 0, mixerLayerPlayable, 1);
        mixerLayerPlayable.SetInputWeight(0, 1.0f);
        mixerLayerPlayable.SetInputWeight(1, 1.0f);
        mixerLayerPlayable.SetLayerMaskFromAvatarMask(1, headMask);

        // Wrap the clips in a playable
        pHappy             = AnimationClipPlayable.Create(playableGraph, happy);
        pHappyTransitionIn = AnimationClipPlayable.Create(playableGraph, happyTransitionIn);
        pAngry             = AnimationClipPlayable.Create(playableGraph, angry);
        pAngryTransitionIn = AnimationClipPlayable.Create(playableGraph, angryTransitionIn);
        pTPose             = AnimationClipPlayable.Create(playableGraph, tPose);

        // Setup Durations for IsDone Checks
        pHappyTransitionIn.SetDuration(happyTransitionIn.length);
        pAngryTransitionIn.SetDuration(angryTransitionIn.length);

        // Connect to Emotion Mixer
        mixerEmotionPlayable.SetInputCount(5); // InputCount needs to be == to the number of connected clips (for normalization purposes)
        playableGraph.Connect(pHappy, 0, mixerEmotionPlayable, 0);
        playableGraph.Connect(pHappyTransitionIn, 0, mixerEmotionPlayable, 1);
        playableGraph.Connect(pAngry, 0, mixerEmotionPlayable, 2);
        playableGraph.Connect(pAngryTransitionIn, 0, mixerEmotionPlayable, 3);
        playableGraph.Connect(pTPose, 0, mixerEmotionPlayable, 4);

        Debug.Log("INputLength: " + mixerEmotionPlayable.GetInputCount());



        // Activate T Pose
        mixerEmotionPlayable.SetInputWeight(4, 1.0f);

        Debug.Log("Happy Transition Time: " + pHappyTransitionIn.GetDuration());

        // Plays the Graph
        playableGraph.Play();
    }
コード例 #12
0
    void normalizeWeights()
    {
        int   length       = mixerEmotionPlayable.GetInputCount();
        float sumOfWeights = 0;

        for (int i = 0; i < length; i++)
        {
            if (mixerEmotionPlayable.GetInputWeight(i) > 0f)
            {
                sumOfWeights += mixerEmotionPlayable.GetInputWeight(i);
            }
        }
        for (int i = 0; i < length; i++)
        {
            if (mixerEmotionPlayable.GetInputWeight(i) > 0f)
            {
                mixerEmotionPlayable.SetInputWeight(i, mixerEmotionPlayable.GetInputWeight(i) / sumOfWeights);
            }
        }

        normalize = false;
    }
コード例 #13
0
    public void Initialize(AnimationClip[] clipArray, Playable owner, PlayableGraph graph)
    {
        owner.SetInputCount(1);
        m_mixerPlayable = AnimationMixerPlayable.Create(graph, clipArray.Length);
        graph.Connect(m_mixerPlayable, 0, owner, 0);
        owner.SetInputWeight(0, 1);

        //根据clipArray创建AnimationClipPlayable并连接
        for (int clipIndex = 0; clipIndex < m_mixerPlayable.GetInputCount(); ++clipIndex)
        {
            graph.Connect(AnimationClipPlayable.Create(graph, clipArray[clipIndex]), 0, m_mixerPlayable, clipIndex);
        }
    }
コード例 #14
0
        public void RemoveZeroWeightsInputsAnimations(
            AnimationMixerPlayable mixer,
            List <float> blendingWeights,
            List <float> currentWeights,
            List <int> curretClipsIndex,
            List <LogicAnimationsSequence> animationsSequences
            )
        {
            int size = mixer.GetInputCount();

            for (int i = 0; i < size; i++)
            {
                if (currentWeights[i] <= 0f)
                {
                    int sequenceMixerInputsCount = mixer.GetInput(i).GetInputCount();
                    if (sequenceMixerInputsCount > 0)
                    {
                        for (int mixerInputInputsIndex = 0; mixerInputInputsIndex < sequenceMixerInputsCount; mixerInputInputsIndex++)
                        {
                            mixer.GetInput(i).GetInput(mixerInputInputsIndex).Destroy();
                        }
                        for (int as_Index = 0; as_Index < animationsSequences.Count; as_Index++)
                        {
                            if (curretClipsIndex[i] == animationsSequences[as_Index].dataIndex)
                            {
                                animationsSequences.RemoveAt(as_Index);
                                break;
                            }
                        }
                    }
                    mixer.GetInput(i).Destroy();
                    blendingWeights.RemoveAt(i);
                    curretClipsIndex.RemoveAt(i);
                    currentWeights.RemoveAt(i);
                    for (int j = i + 1; j < size; j++)
                    {
                        // double localTime = ((AnimationClipPlayable)mixer.GetInput(j)).GetTime();
                        float    _weight = mixer.GetInputWeight(j);
                        Playable clip    = mixer.GetInput(j);
                        // clip.SetTime(localTime);
                        mixer.DisconnectInput(j);
                        mixer.ConnectInput(j - 1, clip, 0);
                        mixer.SetInputWeight(j - 1, _weight);
                    }
                    i--;
                    size--;
                    mixer.SetInputCount(size);
                }
            }
        }
コード例 #15
0
    public Playable GetInput(int layer, int index)
    {
        AnimationMixerPlayable mixer = GetMixer(layer);

        if (mixer.Equals(AnimationMixerPlayable.Null))
        {
            return(Playable.Null);
        }
        if (index >= mixer.GetInputCount())
        {
            return(Playable.Null);
        }

        return(mixer.GetInput(index));
    }
コード例 #16
0
        // 取得可用的或新的输入索引
        private int GetInputIndex(AnimationMixerPlayable mixerPlayable)
        {
            var count = mixerPlayable.GetInputCount();

            for (int i = 0; i < count; i++)
            {
                var p = mixerPlayable.GetInput(i);
                if (p.IsNull())
                {
                    mixerPlayable.SetInputWeight(i, 0);
                    return(i);
                }
            }
            mixerPlayable.SetInputCount(count + 1);
            return(count); //index
        }
コード例 #17
0
ファイル: AnimMixer.cs プロジェクト: mrcece/MotionFramework
        /// <summary>
        /// 播放指定动画
        /// </summary>
        public void Play(AnimState animState, float fadeDuration)
        {
            // 重新激活混合器
            _isQuiting = false;
            StartWeightFade(1f, 0);

            if (IsContains(animState) == false)
            {
                // 优先插入到一个空位
                int index = _states.FindIndex(s => s == null);
                if (index == -1)
                {
                    // Increase input count
                    int inputCount = _mixer.GetInputCount();
                    _mixer.SetInputCount(inputCount + 1);

                    animState.Connect(_mixer, inputCount);
                    _states.Add(animState);
                }
                else
                {
                    animState.Connect(_mixer, index);
                    _states[index] = animState;
                }
            }

            for (int i = 0; i < _states.Count; i++)
            {
                var state = _states[i];
                if (state == null)
                {
                    continue;
                }

                if (state == animState)
                {
                    state.StartWeightFade(1f, fadeDuration);
                    state.PlayNode();
                }
                else
                {
                    state.StartWeightFade(0f, fadeDuration);
                    state.PauseNode();
                }
            }
        }
コード例 #18
0
    public void PlayClip(string clipName)
    {
        if (!clipIndexes.ContainsKey(clipName))
        {
            return;
        }
        int playingClipIndex = clipIndexes[clipName];

        for (int i = 0; i < animationMixer.GetInputCount(); i++)
        {
            if (i != playingClipIndex)
            {
                animationMixer.SetInputWeight(i, 0);
            }
            else
            {
                animationMixer.SetInputWeight(i, 1);
            }
        }
    }
コード例 #19
0
    private void ConnectInput(int index)
    {
        StateInfo state = m_States[index];
        AnimationMixerPlayable mixer = GetMixer(state.layer);

        if (mixer.Equals(AnimationMixerPlayable.Null))
        {
            throw new Exception("Can not get mixer at layer:" + state.layer);
        }

        int stateCountByLayer = m_States.GetCountByLayer(state.layer);

        if (stateCountByLayer > mixer.GetInputCount())
        {
            mixer.SetInputCount(stateCountByLayer);
        }

        mixer.DisconnectInput(state.indexAtLayer);
        graph.Connect(state.playable, 0, mixer, state.indexAtLayer);
    }
コード例 #20
0
    private StateInfo DoAddClip(string name, AnimationClip clip)
    {
        //Start new State
        StateInfo newState = m_States.InsertState();

        newState.Initialize(name, clip, clip.wrapMode);
        //Find at which input the state will be connected
        int index = newState.index;

        //Increase input count if needed
        AnimationMixerPlayable mixer = AddMixerWhenNotExist(newState.layer);

        if (!mixer.Equals(AnimationMixerPlayable.Null))
        {
            int stateCountByLayer = m_States.GetCountByLayer(newState.layer);
            if (stateCountByLayer == mixer.GetInputCount())
            {
                mixer.SetInputCount(stateCountByLayer);
            }
        }

        var clipPlayable = AnimationClipPlayable.Create(graph, clip);

        clipPlayable.SetApplyFootIK(false);
        clipPlayable.SetApplyPlayableIK(false);
        if (!clip.isLooping || newState.wrapMode == WrapMode.Once)
        {
            clipPlayable.SetDuration(clip.length);
        }
        newState.SetPlayable(clipPlayable);
        newState.Pause();

        if (keepStoppedPlayablesConnected)
        {
            ConnectInput(newState.index);
        }

        return(newState);
    }
コード例 #21
0
        private bool AnimationClipIsPlaying(AnimationMixerPlayable mixerPlayable, AnimationClip clip, out AnimationClipPlayable playable)
        {
            var count = mixerPlayable.GetInputCount();

            for (int i = 0; i < count; i++)
            {
                var p = mixerPlayable.GetInput(i);
                if (p.IsNull() == false)
                {
                    if (p.IsPlayableOfType <AnimationClipPlayable>())
                    {
                        playable = (AnimationClipPlayable)p;
                        if (((AnimationClipPlayable)p).GetAnimationClip() == clip)
                        {
                            return(true);
                        }
                    }
                }
            }
            playable = (AnimationClipPlayable)Playable.Null;
            return(false);
        }
コード例 #22
0
        /// <summary>
        /// Update is called once per frame
        /// </summary>
        private void Update()
        {
            if (animationMixer.GetInputCount() == 0 || currentAnimationList.Count == 0)
            {
                // No valid clip input.
                return;
            }

            AnimationComponent firstAnimation  = currentAnimationList[0];
            AnimationComponent secondAnimation = null;

            if (currentAnimationList.Count >= 2)
            {
                secondAnimation = currentAnimationList[1];
            }

            if (firstAnimation != null)
            {
                switch (firstAnimation.CurrentStatus)
                {
                case AnimationComponent.Status.Pending:
                    firstAnimation.Start();
                    break;

                case AnimationComponent.Status.Processing:
                    firstAnimation.Tick();
                    break;

                case AnimationComponent.Status.Done:
                    if (currentAnimationList.Count == 1)
                    {
                        firstAnimation
                        .SetStartBlendingTime(-1.0f)
                        .SetEndBlendingTime(99999.0f)
                        .Reset();
                    }
                    else if (currentAnimationList.Count >= 2)
                    {
                        currentAnimationList.Remove(firstAnimation);
                    }
                    break;
                }
                // We can start blend next clip.
                if (firstAnimation.CanStartNextClip)
                {
                    switch (secondAnimation.CurrentStatus)
                    {
                    case AnimationComponent.Status.Pending:
                        secondAnimation.Start();
                        break;

                    case AnimationComponent.Status.Processing:
                        secondAnimation.Tick();
                        break;

                    case AnimationComponent.Status.Done:
                        // Impossibile
                        break;
                    }
                }
            }
        }
コード例 #23
0
        public void CreateBlendMotionMatchingAnimation(
            MotionMatchingData data,
            int dataIndex,
            AnimationMixerPlayable stateMixer,
            double localTime,
            float blendTime,
            List <float> blendingSpeeds,
            List <float> currentWeights,
            List <LogicAnimationsSequence> animationsSequences,
            bool passIK,
            bool passFootIK,
            float newInputStartWeight = 0f,
            float minWeightToAchive   = 0f,
            float speedMulti          = 1f
            )
        {
            if (stateMixer.GetInputCount() > 0)
            {
                if (currentWeights[currentWeights.Count - 1] >= minWeightToAchive)
                {
                    blendingSpeeds[blendingSpeeds.Count - 1] = -(stateMixer.GetInputWeight(stateMixer.GetInputCount() - 1) / blendTime);
                }
            }
            currentWeights.Add(newInputStartWeight);
            blendingSpeeds.Add(1f / blendTime);

            switch (data.dataType)
            {
            case AnimationDataType.SingleAnimation:
                AnimationClipPlayable playable_SA = AnimationClipPlayable.Create(graph, data.clips[0]);
                playable_SA.SetApplyPlayableIK(passIK);
                playable_SA.SetApplyFootIK(passFootIK);
                playable_SA.SetTime(localTime - Time.deltaTime);
                playable_SA.SetTime(localTime);
                playable_SA.SetSpeed(speedMulti);
                stateMixer.AddInput(playable_SA, 0, newInputStartWeight);
                break;

            case AnimationDataType.BlendTree:
                AnimationMixerPlayable mixerPlayable = AnimationMixerPlayable.Create(this.graph);
                stateMixer.AddInput(mixerPlayable, 0, newInputStartWeight);

                for (int i = 0; i < data.clips.Count; i++)
                {
                    AnimationClipPlayable playable_BT = AnimationClipPlayable.Create(this.graph, data.clips[i]);
                    playable_BT.SetApplyPlayableIK(passIK);
                    playable_BT.SetApplyFootIK(passFootIK);
                    playable_BT.SetTime(localTime - Time.deltaTime);
                    playable_BT.SetTime(localTime);
                    playable_BT.SetSpeed(speedMulti);
                    mixerPlayable.AddInput(playable_BT, 0, data.blendTreeWeights[i]);
                }
                break;

            case AnimationDataType.AnimationSequence:
                animationsSequences.Add(new LogicAnimationsSequence(data, dataIndex));
                int new_ASIndex = animationsSequences.Count - 1;
                animationsSequences[new_ASIndex].mixer = AnimationMixerPlayable.Create(this.graph);
                stateMixer.AddInput(animationsSequences[new_ASIndex].mixer, 0, newInputStartWeight);
                animationsSequences[new_ASIndex].CreateAnimationsInTime((float)localTime, this, passIK, passFootIK);
                break;
            }
        }
コード例 #24
0
    private void UpdateStates(float deltaTime)
    {
        mustUpdateWeights.Clear();
        totalWeights.Clear();

        for (int i = 0; i < m_States.Count; i++)
        {
            StateInfo state = m_States[i];

            //Skip deleted states
            if (state == null)
            {
                continue;
            }

            //Update crossfade weight
            if (state.fading)
            {
                state.SetWeight(Mathf.MoveTowards(state.weight, state.targetWeight, state.fadeSpeed * deltaTime));
                if (Mathf.Approximately(state.weight, state.targetWeight))
                {
                    state.ForceWeight(state.targetWeight);
                    if (state.weight == 0f)
                    {
                        state.Stop();
                    }
                }
            }

            if (state.layerDirty >= 0)
            {
                AnimationMixerPlayable lastMixer = GetMixer(state.layerDirty);
                if (!lastMixer.Equals(AnimationMixerPlayable.Null))
                {
                    if (lastMixer.GetInput(state.indexAtLayer).Equals(state.playable))
                    {
                        graph.Disconnect(lastMixer, state.indexAtLayer);
                    }
                }

                AnimationMixerPlayable mixer = AddMixerWhenNotExist(state.layer);
                if (mixer.Equals(AnimationMixerPlayable.Null))
                {
                    throw new Exception("Can not get mixer at layer:" + state.layer);
                }

                state.indexAtLayer = m_States.GetAvailableIndexAtLayer(state.layer, state);

                int stateCountByLayer = m_States.GetCountByLayer(state.layer);
                if (stateCountByLayer > mixer.GetInputCount())
                {
                    mixer.SetInputCount(stateCountByLayer);
                }

                graph.Connect(state.playable, 0, mixer, state.indexAtLayer);
            }

            if (state.enabledDirty)
            {
                if (state.enabled)
                {
                    state.Play();
                }
                else
                {
                    state.Pause();
                }

                if (!keepStoppedPlayablesConnected)
                {
                    AnimationMixerPlayable mixer = GetMixer(state.layer);
                    if (mixer.Equals(AnimationMixerPlayable.Null))
                    {
                        throw new Exception("Can not get mixer at layer:" + state.layer);
                    }
                    Playable input = mixer.GetInput(state.indexAtLayer);
                    //if state is disabled but the corresponding input is connected, disconnect it
                    if (input.IsValid() && !state.enabled)
                    {
                        DisconnectInput(i);
                    }
                    else if (state.enabled && !input.IsValid())
                    {
                        ConnectInput(state.index);
                    }
                }
            }

            if (state.enabled && state.wrapMode == WrapMode.Once)
            {
                bool  stateIsDone = state.isDone;
                float speed       = state.speed;
                float time        = state.GetTime();
                float duration    = state.playableDuration;

                stateIsDone |= speed < 0f && time < 0f;
                stateIsDone |= speed >= 0f && time >= duration;
                if (stateIsDone)
                {
                    state.Stop();
                    state.Disable();
                    if (!keepStoppedPlayablesConnected)
                    {
                        DisconnectInput(state.index);
                    }
                }
            }

            if (!totalWeights.ContainsKey(state.layer))
            {
                totalWeights.Add(state.layer, 0.0f);
            }
            if (!mustUpdateWeights.ContainsKey(state.layer))
            {
                mustUpdateWeights.Add(state.layer, false);
            }
            totalWeights[state.layer] += state.weight;
            if (state.weightDirty)
            {
                mustUpdateWeights[state.layer] = true;
            }
            state.ResetDirtyFlags();
        }

        var e = mustUpdateWeights.GetEnumerator();

        while (e.MoveNext())
        {
            if (e.Current.Value)
            {
                float totalWeight = totalWeights[e.Current.Key];

                bool hasAnyWeight = totalWeight > 0.0f;
                for (int i = 0; i < m_States.Count; i++)
                {
                    StateInfo state = m_States[i];
                    if (state == null || state.layer != e.Current.Key)
                    {
                        continue;
                    }
                    AnimationMixerPlayable mixer = GetMixer(state.layer);
                    if (mixer.Equals(AnimationMixerPlayable.Null))
                    {
                        throw new Exception("Can not get mixer at layer:" + state.layer);
                    }

                    float weight = hasAnyWeight ? state.weight / totalWeight : 0.0f;
                    mixer.SetInputWeight(state.indexAtLayer, weight);
                }
            }
        }

        mustUpdateWeights.Clear();
        totalWeights.Clear();
    }