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?
Answer by WARdd · Sep 08, 2017 at 09:11 PM
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);
             }
         }
     }
Answer by RedGirafeGames · Nov 13, 2020 at 11:22 PM
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...
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                