Description

When the same AnimMonotage is played again while moving with MotionWarping & RootMotion, UAnimNotifyState_MotionWarping does not recognize it.

 

From licensee:

The issue was that in URootMotionModifier::Update it tries to remove invalid animations by checking if the animation is still valid and that its the same as the cached animation, if not it marks it for modifier for removal.

The problem is that if you replay the same montage, while it's still in the warping window, it doesn't know that is needs to reset, as its only checking if the animation asset has changed which is has not. Thus it keeps playing out the only warping window with its cached values that promptly gets shut down. Effectively its not starting a new warping window because it believes its already active, the old one gets shutdown and you end up with a result that no warping occurs when it should.

I've put in a fix which checks the montage instance id, caches it like it does with the animation asset then checks to ensure it has not changed. I've recently modified the fix as we updated to 5.1 but it does have some limitations, it only works for montages and it doesn't really support replication, which I believe 5.1 added support to check SavedMoved during replay / rollback.

void URootMotionModifier::Update(const FMotionWarpingUpdateContext& Context)
{
   const ACharacter* CharacterOwner = GetCharacterOwner();
   if (CharacterOwner == nullptr)
   {
      return;
   }
   
   // CHANGE BEGIN ++++++++++++++++++++
   // Added: Fixed issue which motion warping failed to reset the warping modifiers when a new montage instance played with the same montage.
   if (Context.MontageInstanceID != INDEX_NONE)
   {
      if(!MontageInstanceID.IsSet())
      {
         MontageInstanceID = Context.MontageInstanceID;
      }
      
      // Mark for removal if our animation is not relevant anymore
      if (MontageInstanceID != Context.MontageInstanceID)
      {
         UE_LOG(LogMotionWarping, Verbose, TEXT("MotionWarping: Marking RootMotionModifier for removal. Reason: Animation is not valid. Char: %s Current Animation: %s. Window: Animation: %s [%f %f] [%f %f]"),
            *GetNameSafe(CharacterOwner), *GetNameSafe(Context.Animation.Get()), *GetNameSafe(Animation.Get()), StartTime, EndTime, PreviousPosition, CurrentPosition);
 
         SetState(ERootMotionModifierState::MarkedForRemoval);
         return;
      }
   }
   // CHANGE END ++++++++++++++++++++++
   
   // Mark for removal if our animation is not relevant anymore
   if (!Context.Animation.IsValid() || Context.Animation.Get() != Animation)
   {
      UE_LOG(LogMotionWarping, Verbose, TEXT("MotionWarping: Marking RootMotionModifier for removal. Reason: Animation is not valid. Char: %s Current Animation: %s. Window: Animation: %s [%f %f] [%f %f]"),
         *GetNameSafe(CharacterOwner), *GetNameSafe(Context.Animation.Get()), *GetNameSafe(Animation.Get()), StartTime, EndTime, PreviousPosition, CurrentPosition);
 
      SetState(ERootMotionModifierState::MarkedForRemoval);
      return;
   }
 
   ......
} 
Steps to Reproduce
  1. Open attached repro proj
  2. PIE
  3. Press Q
  4. Character move to white cube
  5. Press Q
  6. Character move to other cube

expect : print OnWarpBegin log when 5
result : does not print

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-173786 in the post.

1
Login to Vote

Backlogged
ComponentUE - Anim - Gameplay
Affects Versions5.05.1
CreatedJan 11, 2023
UpdatedAug 1, 2023