animator.crossfade() not working properly

I’m trying to create a class that can save and load the exact animation state of an animator. I can load up a normal animation state just fine using animator.Play(), the problem is I can’t seem to load a transition between 2 states properly.

my code looks like this right now:

[Serializable]
	class AnimState {
        //variables...

		/// <summary>
		/// Apply this AnimState object to the given animator: LOADING
		/// </summary>
		public void Apply(int layer, Animator anim) {
			//current animation info
			anim.Play(hash, layer, time);
			anim.SetLayerWeight(layer, weight);

			//transition info
			if(inTransition) {
				anim.CrossFade(transitionHash, transitionDuration, layer, transitionTime);
			}
		}
	}

But the result doesn’t set the animator in the transition state between the two animations, it just puts the animator in either the source or the goal state completely. Did I misunderstand how CrossFade() works? How should I accomplish the desired effect?

Managed to find the solution, just posting it for people who might stumble on it.
CrossFade() can be used to start a transition, but the animator needs to be updated manually to get it to the right point in time. Getting this to work requires a few nasty workarounds, but I arrived at a reasonable solution:

[Serializable]
	class AnimState {
		//MAKE SURE THAT NEXT STATE ANIMATION OFFSET == 0
		//variables...

		/// <summary>
		/// Create AnimState object using state of given anim: SAVING
		/// </summary>
		public AnimState(int layer, Animator anim) {

			//retrieve current animation info
			AnimatorStateInfo info = anim.GetCurrentAnimatorStateInfo(layer);
			this.currentHash = info.fullPathHash;
			this.currentLength = info.length;
			this.currentTime = info.normalizedTime * currentLength;
			this.weight = anim.GetLayerWeight(layer); 

			//if there is a transition, move on and gather transition info
			inTransition = anim.IsInTransition(layer);
			if(inTransition) {
				AnimatorTransitionInfo transInfo = anim.GetAnimatorTransitionInfo(layer);
				AnimatorStateInfo nextInfo = anim.GetNextAnimatorStateInfo(layer);

				if(transInfo.normalizedTime == 0f) { 
					//move animation forward so we have proper info to work with.
					anim.Update(timeShift);
					transInfo = anim.GetAnimatorTransitionInfo(layer);
					nextInfo = anim.GetNextAnimatorStateInfo(layer);
					anim.Update(-timeShift);
				}

				//retrieve all necessary info
				nextHash = nextInfo.fullPathHash;
				nextLength = nextInfo.length;
				transitionTime = nextInfo.normalizedTime * nextLength;
				transitionLength = transitionTime / transInfo.normalizedTime;
			}
		}

		/// <summary>
		/// Apply this AnimState object to the given animator: LOADING
		/// </summary>
		public void Apply(int layer, Animator anim) {
			//apply current animation info
			anim.Play(currentHash, layer, currentTime/currentLength);
			anim.SetLayerWeight(layer, weight);
			anim.Update(0f);

			//if necessary, apply transition info
			if(inTransition) {
				//rewind current animation, so it can be wound forward along with the fading
				float playTime = Util.PosModulo((currentTime - transitionTime) / currentLength, 1f);
				anim.Play(currentHash, layer, playTime);
				anim.Update(0f);

				//set crossfade time and update to the required point
				float crossPlayTime = Util.PosModulo(transitionTime / nextLength, 1f);
				anim.CrossFade(nextHash, transitionLength / currentLength, layer, crossPlayTime);
				anim.Update(transitionTime);
			}
		}
	}

After hours of tests I ended with this version (based on yours, thanks @WARdd ).
An advantage is that it works even with animator.speed == 0 (which is not the case using the “length” properties because they have “infinity” values in that case)

Get State :

    private void TakeSnap()
    {
        AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(layer);
        currentHash = info.fullPathHash;
        currentLength = info.length;
        normalizedTime = info.normalizedTime;

        inTransition = animator.IsInTransition(layer);
        if (inTransition)
        {
            Debug.Log("In transition...");

            AnimatorTransitionInfo transInfo = animator.GetAnimatorTransitionInfo(layer);
            AnimatorStateInfo nextInfo = animator.GetNextAnimatorStateInfo(layer);

            transitionDuration = transInfo.duration;
            transitionNormalizedTime = transInfo.normalizedTime;
            nextHash = nextInfo.fullPathHash;
            nextNormalizedTime = nextInfo.normalizedTime;
        }
    }

Apply State :

    private void ApplySnap()
    {
        if (inTransition)
        {
            animator.Play(currentHash, layer, normalizedTime);
            animator.Update(0.0f);
            var transitionFixedTime = transitionDuration * transitionNormalizedTime;
            animator.CrossFade(nextHash, transitionDuration, layer, nextNormalizedTime,
                transitionNormalizedTime);
        }
        else
        {
            animator.Play(currentHash, layer, normalizedTime);
        }
    }

Some Unity documentation is really a shame… not even possible to understand how to use crossFade without countless tests…