Mute sound events from animation sequence in a Montage

Hello all.

Is there a way to mute the sound events from an animation sequence which has been inserted into an anim montage?

We’ve created an anim seq then an anim montage with the anim seq in it.
The problem is that both the anim seq and montage carry their own sound events.
When the montage plays, the sounds in the seq and the montage are played simultaneously (which is not we want).

Is it possible to mute the sounds in the seq and only play the sound in the montage (when the seq is triggered by the montage)?

PS:
I’ve looked into some C++ code:
It seems that same notify weight is passed in when the code adds events either from anim seq or anim montage.
So I guess that adjusting event notification weight wouldn’t work.

The closest solution I’ve found so far (by digging through engine source) is add an separate “anim notifies weight” property to UAnimMontage then pass it to FAnimMontageInstance. Then I could make the weights of all my montage events lower than the notifies weight but the weights of my anim seq events higher than the property so that all seq events would be filtered out.
Right now the FAnimMontageInstance.NotifyWeight is tied to anim blend weight.

Is there still an option which does not require engine change?

Hi lzhang,

Are you using a custom AnimNotify? If not, you can create one that would contain both the sound and the volume to play the sound at.

Hi Darkwind.

Not yet but I did think of the option you proposed. I could add a “volume” property to my custom AnimNotify. But I couldn’t simply turn off the volume since it still needs to be audible when the anim seq is played directly. It doesn’t seem to be possible to override such a property in an anim montage, and I couldn’t see how to tell if an anim seq is played directly or within a montage in UAnimNotify.Notify. Even if I could, ideally I should be able to tell from which montage an anim seq is being played (doesn’t look like kinda information which should be available in anim seq / notify). The goal was to turn off the volume only when the anim seq is played from within a montage.

Or maybe I missed something?

Hi lzhang,

I do not know if it is possible from within Blueprint, but the Notify method on UAnimNotify is provided both the skeletal mesh component as well as the animation. The animation is provided as a UAnimSequenceBase, which is a base class for both montages and sequences. If you want to play the sound in sequences but not montages, you could simply check to see if the passed in animation is either a UAnimSequence or a UAnimMontage.

It seems that the one UAnimNotify_PlaySound::Notify received is always UAnimSequence.
I am not sure though if this only happens under montage preview mode.

Nevertheless, it might be more elegant from engine point of view to not emit events at all rather than hack the events themselves. After all user could have similar problems on events other than PlaySound.

Hi lzhang,

Wanting to only play a sound in an animation sequence and not a montage is a very specific, niche feature request so it is highly unlikely that such a thing would be natively supported by the engine. Not emitting events at all is, for the most part, highly undesired, so again it is unlikely that that would happen.

Looking at the source, an animation montage does use an animation sequence for the preview. Have you tried checking the type in practice, and not while previewing the montage?

I just tried Play-in-Editor - same result as Preview.
Callstacks were a bit different but I could only get UAnimSequence through Notify.

  • Montage Preview

UAnimNotify_PlaySound::Notify
UAnimInstance::TriggerSingleAnimNotify
UAnimInstance::TriggerAnimNotifies
UAnimInstance::DispatchQueuedAnimEvents
USkeletalMeshComponent::ConditionallyDispatchQueuedAnimEvents
USkeletalMeshComponent::FinalizeAnimationUpdate
USkeletalMeshComponent::PostAnimEvaluation
USkeletalMeshComponent::RefreshBoneTransforms
UDebugSkelMeshComponent::RefreshBoneTransforms
USkinnedMeshComponent::TickComponent
USkeletalMeshComponent::TickComponent
UDebugSkelMeshComponent::TickComponent
FActorComponentTickFunction::ExecuteTick::__l2::::operator()
FActorComponentTickFunction::ExecuteTickHelper< >
FActorComponentTickFunction::ExecuteTick::__l2:: & ExecuteTickFunc)
FActorComponentTickFunction::ExecuteTick
FTickFunctionTask::DoTask
TGraphTask::ExecuteTask
FBaseGraphTask::Execute

  • Play-in-Editor

UAnimNotify_PlaySound::Notify
UAnimInstance::TriggerSingleAnimNotify
UAnimInstance::TriggerAnimNotifies
UAnimInstance::DispatchQueuedAnimEvents
USkeletalMeshComponent::ConditionallyDispatchQueuedAnimEvents
USkeletalMeshComponent::FinalizeAnimationUpdate
USkeletalMeshComponent::PostAnimEvaluation
USkeletalMeshComponent::CompleteParallelAnimationEvaluation
FParallelAnimationCompletionTask::DoTask
TGraphTask::ExecuteTask
FBaseGraphTask::Execute

It’s OK if there is no official option for this yet.
We’ve been looking into the path of maintaining a custom engine build. It’s just that we did prefer a workaround, if possible, without having to touch the codebase ourselves.
And, it would be more than helpful if we could get some clue on WHY it is what it is :slight_smile:

Hi lzhang,

After looking at the source (specifically at the anim montage factory in the editor source), it looks like it is by design that an anim sequence doesn’t know anything about the montage it is in. That would make sense to me because a sequence can appear in multiple montages or be played on its own.

To avoid having to edit the engine’s source, the simplest solution would be to duplicate the sequence. You could have one version that has the notifies to play the sound, and another without any notifies. If that wouldn’t work for some reason, you could also have some kind of global state about whether or not notifies should play sound and update that as needed.

Thanks for your help DarkwindRichard :slight_smile:
I suppose that duplicating anim sequence is what we will have to do for now. I will see how many sequences we will have to duplicate then it would become obvious whether to live with this or add a property to the montage class.