Description

When an animation is currently blending out due to automatic blend out or GameplayLogic, further StopMontage with specific BlendOut will not update the time to blend out of the current blending out Animation Montage.

The code will not allow this, because if you follow the current written code :

In

void FAnimMontageInstance::Stop(const FMontageBlendSettings& InBlendOutSettings, bool bInterrupt)

We have :

if (IsStopped() == false)
{
    // If we are using Inertial Blend, blend time should be 0 to instantly stop the montage.
    FAlphaBlendArgs BlendOutArgs = InBlendOutSettings.Blend;
    const bool bShouldInertialize = InBlendOutSettings.BlendMode == EMontageBlendMode::Inertialization;
    BlendOutArgs.BlendTime = bShouldInertialize ? 0.0f : BlendOutArgs.BlendTime;
 
    // do not use default Montage->BlendOut 
    // depending on situation, the BlendOut time can change 
    InitializeBlend(FAlphaBlend(BlendOutArgs));
    BlendStartAlpha = Blend.GetAlpha();
    Blend.SetDesiredValue(0.f);
    Blend.Update(0.0f);
 
    // Only change the active blend profile if the montage isn't stopped. This is to prevent pops on a sudden blend profile switch
    ActiveBlendProfile = InBlendOutSettings.BlendProfile;
 
    if(Montage)
    {
       if (UAnimInstance* Inst = AnimInstance.Get())
       {
          // Let AnimInstance know we are being stopped.
          Inst->OnMontageInstanceStopped(*this);
          Inst->QueueMontageBlendingOutEvent(FQueuedMontageBlendingOutEvent(Montage, bInterrupted, OnMontageBlendingOutStarted));
 
          if (bShouldInertialize)
          {
             // Send the inertial blend request to the anim instance
             Inst->RequestMontageInertialization(Montage, InBlendOutSettings.Blend.BlendTime, InBlendOutSettings.BlendProfile);
          }
       }
    }
}

The line causing problems is

Inst->OnMontageInstanceStopped(*this);

Which ->

ClearMontageInstanceReferences(StoppedMontageInstance);

And remove ActiveMontage like this

ActiveMontagesMap.Remove(MontageStopped);

BUT, in

void UAnimInstance::Montage_StopInternal(TFunctionRef<FMontageBlendSettings(const FAnimMontageInstance*)> AlphaBlendSelectorFunction, const UAnimMontage* Montage /*= nullptr*/)

When called we only stop montage that is referenced in the ActiveMontage map

FAnimMontageInstance* MontageInstance = GetActiveInstanceForMontage(Montage);
if (MontageInstance)
{
    MontageInstance->Stop(AlphaBlendSelectorFunction(MontageInstance));
}

This makes It impossible for Stop to be called multiple times and update the blend time.

If it worked.
Blend time will only update if it lower than previous one.

Steps to Reproduce
  • Create a Blueprint animation, put a Montage node (slot Node) into it.
  • Create a script which switch between 2 montages. 1 will have a "long" BlendOut time, like 1 second. The next want will have no BlendIn time for example.
  • Activate the long blend out Time animation. It will blend out to idle after x time. Activate the script for switching to new animation with specifying to have no BlendOutTime in the StopMontage parameters.
  • See the 2 montages be blended together BUT you have specified to have no blend out when stopping montage

Have Comments or More Details?

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

1
Login to Vote

Unresolved
ComponentUE - Anim - Gameplay
Affects Versions5.4.35.55.4.4
Target Fix5.6
CreatedNov 19, 2024
UpdatedDec 11, 2024
View Jira Issue