概要
UnrealEngine のアニメーションモディファイア(AnimationModifier)についてのメモです。
環境
Windows10
Visual Studio 2017
UnrealEngine 4.24
参考
以下を参考にさせて頂きました、ありがとうございます。
[UE4] UE 4.16 の新機能!Animation Modifier について
UE4 アニメーションモディファイア(Animation Modifier)で自動的にアニメーション情報を追加する
AnimationModifierとは
独立したアセットとして、紐づけたアニメ―ションシーケンスアセットに対してCurve情報やNotify情報を追加できる機能です。(アニメ―ションモンタージュには不可です。)
スケルトンに対して紐づけるとそのスケルトンに紐づいたアニメ―ションシーケンス全てに対して情報が付与されます。
4.16で先行追加された機能のようですが、4.24、4.25でもまだ実験的機能扱いになっています。
前準備 - テスト通知を追加
テスト用のアニメ―ション通知を作成します、イベントタグを通知するものとして以下の様に定義しています。通知クラスはC++である必要はありません。
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "GameplayTagContainer.h"
#include "AnimNotify_TestEvent.generated.h"
class UAnimSequenceBase;
class USkeletalMeshComponent;
struct FGameplayTag;
UCLASS(const, hidecategories=Object, collapsecategories, meta=(DisplayName="TestEvent"))
class TEST_API UAnimNotify_TestEvent : public UAnimNotify
{
GENERATED_BODY()
public:
UAnimNotify_TestEvent();
// Begin UAnimNotify interface
virtual FString GetNotifyName_Implementation() const override;
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;
#if WITH_EDITOR
virtual void ValidateAssociatedAssets() override;
#endif
// End UAnimNotify interface
// イベントタグ
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AnimNotify_TestEvent")
FGameplayTag EventTag;
};
#include "./AnimNotify_TestEvent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Animation/AnimSequenceBase.h"
#include "Abilities/GameplayAbilityTypes.h"
#include "AbilitySystemBlueprintLibrary.h"
#if WITH_EDITOR
#include "Logging/MessageLog.h"
#include "Misc/UObjectToken.h"
#endif
UAnimNotify_TestEvent::UAnimNotify_TestEvent()
: Super()
{
}
void UAnimNotify_TestEvent::Notify(
class USkeletalMeshComponent* MeshComp, // スケルタルメッシュコンポーネント
class UAnimSequenceBase* Animation // アニメ―ション
)
{
AActor* _Actor = MeshComp->GetOwner();
if (_Actor) {
if (!EventTag.IsValid()){
EventTag = FGameplayTag::RequestGameplayTag(FName("Event.Test"));
}
// イベント発行
FGameplayEventData _Payload;
_Payload.Target = _Actor;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(_Actor, EventTag, _Payload);
}
}
// 通知名
FString UAnimNotify_TestEvent::GetNotifyName_Implementation() const
{
return( FString(TEXT("TestEvent")) );
}
#if WITH_EDITOR
void UAnimNotify_TestEvent::ValidateAssociatedAssets()
{
static const FName NAME_AssetCheck("AssetCheck");
}
#endif
ゲームプレイタグを使用しています、当然タグがないとコールバックエラーがでます。
AnimationModifierの使用(BP)
ブループリントで作成するケースです。
BPを作成
AnimationModifierを継承してBPを作成します。
作成したBPに対し、適用イベントOnApply
と元に戻すイベントOnRevert
を以下の様に書きます。
テストコードではアニメ―ショントラック追加と通知追加をしてみます。
OnApply
では Add Animation Notify Track
でアニメ―ショントラック[EventTr]を追加してそのトラックに対し、Add Animation Notify Event
で通知[TestEvent] を追加しています。
OnRevert
ではRemove Animation Notify Events by Name
にて[TestEvent]を削除して、Remove Animation Notify Track
でアニメ―ショントラック[EventTr]を消しています。(この場合、アニメ―ショントラックだけ消せば通知も消えます)
また、OnRevert
はOnApply
で追加した内容を全部消す形で実装しないと、複数回適用した場合、データが意図しない形になるので注意が必要です。
アニメ―ションシーケンスに適用する
アニメ―ションシーケンスの[アニメ―ションデータモディファイアブループリント管理のタブ]から先ほど作成したBPを選択し追加します。
[すべてのモディファイアを適用]ボタンを押下するとBPのOnApply
での内容で適用されます。
右クリックで「モディファイアを適用」「モディファイアを取り消す」「モディファイアを削除」が選択できます。どれを選んでも OnRevert
イベントが一回発生するようです。
適用結果
「モディファイアを適用」をした後がこの状態になります。
[EventTr]トラックが追加され、そこに通知[TestEvent]が追加されています。
「モディファイアを取り消す」を選択すると最初の状態に戻りますが、OnRevert
処理で、OnApply
で追加した内容を全部消さないと以下のようなおかしな状態になってしまいますので注意が必要です。
AnimationModifierの使用(C++)
C++で作成するケースです。エディタ用モジュールで作成しないとパッケージ時にエラーがでてしまいますので注意が必要です。
uprojectの設定
.uproject
の AdditionalDependencies
に AnimationModifiers
を追加する必要があります。
"Modules": [
{
"Name": "MyGame",
"Type": "Runtime",
"LoadingPhase": "Default",
"AdditionalDependencies": [
"Engine",
"UMG",
"CoreUObject"
]
},
{
"Name": "MyGameEd",
"Type": "Editor",
"LoadingPhase": "PostEngineInit",
"AdditionalDependencies": [
"AnimationModifiers"
]
}
],
C++クラスを作成
関連ソース
"Engine\Source\Editor\AnimationModifiers\Public\AnimationModifier.h"
AnimationModifierクラスを継承してC++クラスを追加します。
追加したクラスに対し、OnApply_Implementation
とOnRevert_Implementation
をオーバーライドします。
以下BPと処理的には全く同じになるサンプルコードです。
#include "CoreMinimal.h"
#include "AnimationModifier.h"
#include "MyAnimationModifier.generated.h"
UCLASS()
class TESTEDITOR_API UMyAnimationModifier : public UAnimationModifier
{
GENERATED_BODY()
public:
// 通知
virtual void OnApply_Implementation(UAnimSequence* AnimationSequence) override;
// 戻す
virtual void OnRevert_Implementation(UAnimSequence* AnimationSequence) override;
};
#include "MyAnimationModifier.h"
#include "Animation/AnimSequence.h"
#include "AnimationModifiers/Public/AnimationBlueprintLibrary.h"
#include "{通知クラスのパス}/AnimNotify_TestEvent.h"
void UMyAnimationModifier::OnApply_Implementation(UAnimSequence* AnimationSequence)
{
// アニメ―ショントラックの追加
UAnimationBlueprintLibrary::AddAnimationNotifyTrack(AnimationSequence, TEXT("EventTr"), FLinearColor(0.8f, 0.2f, 0.2f));
// 通知の追加
UAnimationBlueprintLibrary::AddAnimationNotifyEvent(AnimationSequence, TEXT("EventTr"), 0.1f, UAnimNotify_TestEvent::StaticClass());
}
//
void UMyAnimationModifier::OnRevert_Implementation(UAnimSequence* AnimationSequence)
{
// 通知の削除
UAnimationBlueprintLibrary::RemoveAnimationNotifyEventsByName(AnimationSequence, TEXT("TestEvent"));
// アニメ―ショントラックの削除
UAnimationBlueprintLibrary::RemoveAnimationNotifyTrack(AnimationSequence, TEXT("EventTr"));
}
アニメ―ションシーケンスに適用する
BPの時と同様に追加にアニメ―ションシーケンスから「モディファイアを追加」で選択ができるようになります。
適用結果
結果はBPと同様になります。
補足
BPで使えるノードは Animation Blueprint Library
にあります。
C++コードは以下にあります。
"Engine\Source\Editor\AnimationModifiers\Public\AnimationBlueprintLibrary.h"
まとめ
上手く使うと手動で行っていた作業が一部楽になる可能性があるかと思います。特にアクターの違いでアニメ―ションシーケンスアセットは別になっているけれども同じタイミングでの通知を入れないとならないようなケースなどが考えられます。
未だ実験的機能扱いなのが気になるところですが。。