Unreal Engine C++ Notifies: Supercharge Your Animations!
Hey everyone! Today, we're diving into a super useful feature in Unreal Engine: Animation Notifies, specifically how to create and use them in C++. If you've ever wanted to trigger events like footsteps, weapon swings, or any gameplay logic directly from your animations, then notifies are your best friends!
What are Animation Notifies?
At their core, Animation Notifies are events that you can place directly onto animation sequences or montages. Think of them as little markers on your animation timeline. When the animation playback hits that marker, Unreal Engine fires off the notify, allowing you to execute custom C++ or Blueprint code.
This is incredibly powerful because it lets you synchronize gameplay events precisely with your animations without messy timer setups or constant checks in your Tick function.
Why Use C++ for Notifies?
While you can create and handle notifies entirely in Blueprints, using C++ offers several advantages:
- Performance: C++ generally offers better performance, which can be crucial for events that fire rapidly or in performance-intensive situations.
- Control & Complexity: For more complex logic or interactions with other C++ game systems, handling notifies in C++ can be cleaner and more robust.
- Modularity: You can create base C++ notify classes that Blueprints can then inherit from, providing a solid foundation while still allowing designers to tweak specifics.
Creating a Custom C++ AnimNotify
Let's get our hands dirty and create a simple C++ AnimNotify. This notify will just print a message to the log, but you can extend it to do anything!
-
Create a New C++ Class: In the Unreal Editor, go to
Tools -> New C++ Class
. ChooseAnimNotify
as the parent class. Let's name itMyCustomAnimNotify
. -
The Header File (
MyCustomAnimNotify.h
):// MyCustomAnimNotify.h #pragma once #include "CoreMinimal.h" #include "Animation/AnimNotifies/AnimNotify.h" #include "MyCustomAnimNotify.generated.h" UCLASS() class YOURPROJECT_API UMyCustomAnimNotify : public UAnimNotify { GENERATED_BODY() public: // This is the function that will be called when the notify is triggered virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override; // You can add properties here that can be set in the editor! UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Notify Properties") FString MessageToLog = TEXT("Default Notify Message!"); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Notify Properties") int32 LogVerbosity = 0; // 0 for Log, 1 for Warning, 2 for Error };
Notice the
UPROPERTY
macros? These exposeMessageToLog
andLogVerbosity
to the animation editor, so you can customize each instance of your notify! -
The Source File (
MyCustomAnimNotify.cpp
):// MyCustomAnimNotify.cpp #include "MyCustomAnimNotify.h" #include "Components/SkeletalMeshComponent.h" // Required for USkeletalMeshComponent #include "Animation/AnimSequenceBase.h" // Required for UAnimSequenceBase #include "Engine/Engine.h" // For GEngine void UMyCustomAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) { Super::Notify(MeshComp, Animation, EventReference); // Good practice to call parent implementation if (MeshComp && MeshComp->GetOwner()) { FString OwnerName = MeshComp->GetOwner()->GetName(); FString AnimName = Animation ? Animation->GetName() : TEXT("Unknown Animation"); FString FinalMessage = FString::Printf(TEXT("Notify '%s' triggered on '%s' playing animation '%s'"), *MessageToLog, *OwnerName, *AnimName); switch (LogVerbosity) { case 1: UE_LOG(LogTemp, Warning, TEXT("%s"), *FinalMessage); if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, FinalMessage); break; case 2: UE_LOG(LogTemp, Error, TEXT("%s"), *FinalMessage); if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FinalMessage); break; default: UE_LOG(LogTemp, Log, TEXT("%s"), *FinalMessage); if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FinalMessage); break; } } else { UE_LOG(LogTemp, Warning, TEXT("MyCustomAnimNotify: MeshComp or its Owner is null.")); } }
The
Notify
function is where the magic happens.MeshComp
gives you access to the Skeletal Mesh Component playing the animation, andAnimation
is the animation asset itself.EventReference
provides more context about the notify event. -
Compile! Close the editor, compile your C++ code (either from Visual Studio/Rider or by hitting "Compile" in the editor if it's still open and you have live coding enabled, though a full recompile is safer for new classes).
Adding Your C++ Notify in the Editor
Once compiled, you can add your shiny new notify to any animation sequence or montage:
- Open an Animation Sequence or Montage.
- In the Notifies track, right-click where you want the notify to occur.
- Select Add Notify... and you should find your
MyCustomAnimNotify
(or whatever you named it) in the list, likely under a category matching your project name or "Uncategorized". - Select it. You'll see it appear on the timeline.
- Click on the newly added notify instance in the timeline. In the Details panel, you can now edit the
Message To Log
andLog Verbosity
properties we exposed!
(Ideally, replace this with an actual image link or an embedded image if your MDX setup supports it)
If you don't see your C++ notify, ensure your project compiled correctly and try restarting the Unreal Editor.
When Do Notifies Fire? (And Anim Notify States)
- AnimNotify: Fires as a single event when the animation playback reaches its position on the timeline. The code in
Notify()
is executed once. - AnimNotifyState: These are slightly different. They have a duration. They fire an event at the beginning of their duration (
NotifyBegin
), can fire an event every tick they are active (NotifyTick
), and fire an event at the end of their duration (NotifyEnd
). These are great for things like enabling/disabling collision for a weapon swing over a period of time. Creating a C++UAnimNotifyState
is very similar toUAnimNotify
, just inherit fromUAnimNotifyState
and override its respective virtual functions.
Receiving Notify Events in Other C++ Classes (e.g., AnimInstance or Character)
While the UAnimNotify
class itself handles the direct event, sometimes you want the AnimInstance
or the Character Actor to react to these notifies in a more gameplay-specific way.
You can achieve this by:
-
Defining a matching function in your AnimInstance: In your
UAnimInstance
derived class, you can create functions that follow a specific naming convention:AnimNotify_[NotifyName]
. For example, if you create a notify in the editor namedFootstep
, you can have:// In YourAnimInstance.h UFUNCTION() // Important! void AnimNotify_Footstep(); // In YourAnimInstance.cpp void UYourAnimInstance::AnimNotify_Footstep() { // Play footstep sound, spawn particle, etc. UE_LOG(LogTemp, Warning, TEXT("AnimInstance received Footstep Notify!")); // You can get the owning actor (your character) like this: // AActor* OwningActor = GetOwningActor(); // if (AMyCharacter* MyChar = Cast<AMyCharacter>(OwningActor)) { // MyChar->PlayFootstepEffect(); // } }
To use this, you would add an Anim Notify (not your C++ class directly, but a generic one) in the animation editor and name it exactly "Footstep". Unreal's reflection system will automatically find and call this function in your AnimInstance.
-
Using the Notify function in your C++ AnimNotify to call an interface or directly access the owner: In your
UMyCustomAnimNotify::Notify
function, you can get the owner of theMeshComp
and try to cast it to your character class or call an interface function on it.// Inside UMyCustomAnimNotify::Notify AActor* OwnerActor = MeshComp->GetOwner(); if (IMyGameplayInterface* GameplayInterface = Cast<IMyGameplayInterface>(OwnerActor)) { GameplayInterface->Execute_OnCustomNotify(OwnerActor, MessageToLog); // Assuming an interface function } else if (AMyCharacter* MyChar = Cast<AMyCharacter>(OwnerActor)) { // MyChar->HandleMyCustomNotify(MessageToLog); // Call a specific function on your character }
Conclusion
C++ Animation Notifies are a robust way to bridge the gap between animation and gameplay logic in Unreal Engine. They offer precision, performance, and the full power of C++ to trigger complex behaviors.
Start simple, experiment, and see how they can streamline your animation-driven events!
Happy coding!