public override void ProcessFrame(Playable playable, FrameData info, SpineAnimationMixerBehaviour mixer)
        {
            if (skeletonAnimation == null)
            {
                return;
            }
            if (skeleton == null)
            {
                skeleton = skeletonAnimation.Skeleton;
            }

            // New frame.
            if (lastApplyFrame != Time.frameCount)
            {
                if (frameTrackCount > 0)
                {
                    frameAppliedProperties.Clear();
                }

                frameCurrentInputs = 0;
                frameTrackCount    = 0;
            }
            lastApplyFrame = Time.frameCount;

            int currentInputs = mixer.ApplyPlayableFrame(playable, skeleton, frameAppliedProperties, frameTrackCount);

            frameCurrentInputs += currentInputs;

            // EXPERIMENTAL: Handle overriding SkeletonAnimation.AnimationState.
            if (frameCurrentInputs > 0)
            {
                var state = skeletonAnimation.AnimationState;

                if (!firstCleared)
                {
                    firstCleared = true;
                    for (int i = 0; i < 4; i++)
                    {
                        if (state.GetCurrent(i) != null)
                        {
                            state.SetEmptyAnimation(i, fadeOutDuration);
                        }
                    }
                }

                // Update again whenever an animation is playing in the AnimationState. Quite wasteful.
                //if (state.GetCurrent(0) != null) {
                skeleton.UpdateWorldTransform();
                //}
            }

            frameTrackCount++;
        }
 /// <summary>MixerBehaviour ProcessFrame method handler.</summary>
 /// <returns>Returns true if a playable was applied previously</returns>
 public abstract void ProcessFrame(Playable playable, FrameData info, SpineAnimationMixerBehaviour mixer);