4.12 - Notifies no longer work in C++

My game is heavily built around it’s animations and notifies. While curves work, notifies are no longer properly triggered in c++

//BeginPlay
Animation = Cast<UAnimInstance>(Mesh->GetAnimInstance());

//Tick
Animation->AnimNotifies.Num(); // Depreciated
Animation->NotifyQueue.AnimNotifies.Num(); // <-- Also does not work

Both of these now return 0. It looks like AnimNotifies is no longer getting populated properly.

Edit: I’ve uploaded a small (200mb) basic project that shows notifies flat out not working in c++.
http://sky9games.com/Unreal%20Notify%20Bug.rar

Hey -

As you pointed out with your comment, AnimNotifies has been deprecated in 4.12. You should be able to use UAnimInstance::NotifyQueue in its place to get the information you’re looking for.

Cheers

Hey ,

If you check my post again you’ll see that I am using NotifyQueue, directly below the depreciated line you mentioned.

Animation->NotifyQueue.AnimNotifies.Num()

NotifyQueue also no longer works, which is why I created the topic.

Animation->AnimNotifies was actually depreciated in 4.11, so I switched everything to use NotifyQueue, but now in 4.12 neither of them work.

Thank you for the sample project, I now see what you are referring to. A bug report has been entered, UE-31744 , for further investigation.

Cheers

Hi ,
I’m wondering if you can give an update on this bug? There’s been 3 subversions already without the fix, I would have figured Notifies not working at all in C++ would be a pretty high priority.

4.12 has a ton of important fixes we need, so I’d love to switch over as soon as that notify bug is fixed. :slight_smile:

Hey -

The report for this bug is still open for investigation by developers. Unfortunately there is not an expected time for when a fix will be available however I have added a comment to indicate that this is still an issue.

Yikes that is pretty scary. Let’s get this fixed.

Hi

“It looks like AnimNotifies is no longer getting populated properly”
“NotifyQueue also no longer works”
“I would have figured Notifies not working at all in C++ would be a pretty high priority”

I have had some time to look into this and I can assure you there is no issue with Notifies that I can find. Rest assured that the notify system not working would be a major deal and not something that we would leave in the build for a month with no resolution.

As far as I can see your issue stems from the fact that you have no dependency between the component ticking and the actor ticking. This means that the actor ticks at a point where the anim notify data is not valid. Now normally directly reading the contents of the NotifyQueue is not how we handle notify events anyway, instead we add handlers which get called when the notify is triggered.

In order to get the specific code in your example to work you need to add a tick dependency between the actor and skeletal mesh component so that the actor doesn’t tick until the skeletal mesh component is finished. It was enough for me to add the following line to ALyme::BeginPlay

PrimaryActorTick.AddPrerequisite(Mesh, Mesh->PrimaryComponentTick);

Hope this helps, let us know if you have any further questions

Cheers

Martin

Hi mwilson,
Thankyou for the explanation!

It’s strange that my (incorrect) method has worked since 4.9 and only broke in 4.12, but thankyou for showing me the proper way to do that method! I was wondering why I was the only one with the notify problems. Glad to know I’m not crazy and my code was just incorrect all along!

I’d love to transition over to event handlers though I couldn’t seem to find anything useful within c++. Would you be able to show the line of code to bind a handler to the event, or perhaps a link to the documentation?

Thanks!

P.s. I don’t have permission to set your answer to correct, but you should set it if possible, in case others stumble across the same problem I did.

Thankyou for the explanation!

No problem! It is what we are here for :slight_smile:

“It’s strange that my (incorrect) method has worked since 4.9 and only broke in 4.12”

My assumption (though I haven’t investigated this further) is that your method stopped working due to our parallelization of the animation update work.

Previously the notifies would be collected during the skeletal mesh components (SMC) initial tick. Due to the way our actor and component ticks are scheduled this would happen first. When the actor then came to tick they were there ready and waiting. Your original code work through happy coincidence :slight_smile:

Now with parallel update work the SMC ticks as before but just kicks off a task to run on a worker thread. The SMC then gives up its main thread time as before but crucially doesn’t say it is done. The actor gets ticked (again like before) but the notifies are being collected on a worker thread and so are no longer there for the actor to collect. Finally the skeletal mesh component completes its update work on the main thread and the notifies are visible in the queue but as you can see it is already too late for the Actor to see them.

When we make the worker tasks we mark the components tick function as being dependent on both. This means that anything that is made dependent on the SMC’s tick function (like the change I suggested for the actor) knows to wait for both of those tasks to finish before running itself. In the new flow then the SMC ticks, sets up the worker thread, gives up its main thread time, the actor comes in but doesn’t tick because its dependency on the component isn’t fulfilled. Then the component finished and the Actor now gets it chance to tick :slight_smile:

I’d love to transition over to event
handlers though I couldn’t seem to
find anything useful within c++. Would
you be able to show the line of code
to bind a handler to the event, or
perhaps a link to the documentation?

The anim notify documentation is here

Which explains how to set up handlers in anim blueprint assets.
Unfortunately this page makes no mention (as far as I can see and it is late here so I might have missed it) of how to setup native handlers if you have your own custom c++ class derived from UAnimInstance so I’ll go over that briefly:

Basically you define a UFUNCTION on your custom anim instance class. Say if you want to handle the notify “LeftFootStep” you define the following function

UFUNCTION()
void AnimNotify_LeftFootStep(UAnimNotify* Notify);

The “AnimNotify_” is important as the code currently looks for functions with that prefix to act as notify handlers.

I hope that is helpful to you!

Cheers

Martin

Thanks for the explanation once again, it all makes sense now!

Also you are correct, the anim notify (and most in-editor Unreal documentation) makes no mention of c++ whatsoever. Though I’m surprised it’s as simple as prefixed function.

Thanks again for all your help Martin. Saved me a lot of time and headaches! :slight_smile:

I apologize for barging in, but for some reason this didn’t work for me

my character constructor:

static ConstructorHelpers::FObjectFinder<UAnimSequence> anim(TEXT("AnimSequence'/Game/Data/idle.idle'"));
    Anim = anim.Object;

my character beginplay:

PrimaryActorTick.AddPrerequisite(MeshHEDComponent, MeshHEDComponent->PrimaryComponentTick);

Animation = Cast<UAnimInstance>(MeshHEDComponent->GetAnimInstance());

bool bLoop = true;
MeshHEDComponent->PlayAnimation(Anim, bLoop);

my character tick

if (Animation && Animation->NotifyQueue.AnimNotifies.Num() > 0)
	{
		LogWarning("Notify!");
	}

I’m using a multi-mesh, if that makes any difference. my understanding was that at least a begin/tick/end notifies should happen by default out of the bat

Please let me know if I’m missing anything, maybe I’m using the code in the wrong place…

Thanks!

Hey fmaacmab-

Can you add a breakpoint at the if (Animation && Animation->NotifyQueue.AnimNotifies.Num() > 0) line and let me know the value of Animation when the breakpoint is triggered?

Thank you very much for your reply !

for transparency, in the sequence described in my previous post, the animation is null

Animation = Cast<UAnimInstance>(MeshHEDComponent->GetAnimInstance());
bool bLoop = true;
MeshHEDComponent->PlayAnimation(Anim, bLoop);

But this was me just shuffling around code during troubleshooting, because my original attempt looks like this

bool bLoop = true;
MeshHEDComponent->PlayAnimation(Anim, bLoop);
Animation = Cast<UAnimInstance>(MeshHEDComponent->GetAnimInstance());

in this sequence the animation is populated as AnimSingleNodeInstance. But unfortunately the notify queue shows only an empty AnimNotifies array.

Thank you again for your reply!

Comparing against the code provided by your animation is being set correctly even though the AnimNotifies array appears empty. Animation code is not my specialty, however can you try removing the Animation->NotifyQueue.AnimNotifies.Num() > 0 from the if statement in your Tick function and see if that helps?

hi , thank you very much for your reply! after removing Animation->NotifyQueue.AnimNotifies.Num() > 0 , as expected I started to get "Notify!" in the logs every frame/tick because Animation != nullptr so is returns true every frame. which unfortunately is not what I’m looking for, because I need EndNotify so I can trigger the correct branch in my behavior tree :(. Thanks!

hi , I extended AnimInstance, made a blueprint out of it, and added a custom notify at the last frame of my animation, which correctly populated NotifyQueue.AnimNotifies. so custom notifies seem to be working. For now this manual workaround works for me, as I don’t have that many animations this early in preproduction.

Would you mind confirming that this is a known issue, and that there are plans to rectify it in future releases ( if not already on the roadmap, I apologize if I missed it ). If needed for your lab, I can provide my project.

Thanks!

Can you explicitly state what you believe the issue to be? The original issue for this post / bug report entered (UE-31744) was a result of PrimaryActorTick.AddPrerequisite(Mesh, Mesh->PrimaryComponentTick); missing from the BeginPlay() function of 's original project. After adding this line of code, the original project functioned as expected. Additionally, having a copy of your project to test against would be helpful in the investigation of the issue.

Hi fmaacmab

I have been on holiday so apologies for not chiming in on this sooner.

Would you mind confirming that this is
a known issue, and that there are
plans to rectify it in future releases

There are currently no known issues with this. There isn’t a lot to go on in your posts and from what you have described it should work. If you could make an example project displaying your issue that we could then debug here that would be really helpful :slight_smile:

Cheers

Martin