はじめに
Animation ModifierはUE4の頃からあり、Animation SequenceにおけるAnim NotifyやAnim CurveなどのセットアップをBP/C++から一括で行うことができる機能です。「各ボーンの位置を元に、足音用のAnim Notifyを自動的に追加する」といったことができるため、特にアニメーションの数が多いプロジェクトでは非常に便利です。
そして、UE5からはDistance MatchingというAnimation Modifierの利用が前提となった機能が追加され、今後は更にAnimation Modifierが重要になってきそうです。
しかし、現状(UE5.1)では「Animationエディタ(Persona)のAnimation Data Modifiers」か、「Animation Sequenceアセットの右クリックメニュー」からしかAnimation Modifierを実行できません。
せっかくアニメーションに関する面倒な作業を自動化してくれる仕組みなのに、それを実行するには手作業が必要という状況になっています。
めんどうですよね、勝手に実行してアニメーションデータをいい感じにして欲しい所です。
なので、今回はアセットの(再)インポート時などのタイミングで自動的にAnimation Modifierを走らせる方法について紹介します。
Animation Modifierを外部から実行する方法について
残念ながら…Animation Modifierを外部から呼び出すにはC++が必須になります。といっても、既に用意されている関数を呼び出すだけなのでかんたんです。なお、エディタ専用機能を使うことになるため、Editorモジュールで実装することを強く推奨します!
#include "MyEditorBlueprintLibrary.h"
#include "AnimationModifiersAssetUserData.h"
#include "AnimationModifier.h"
#include "IAnimationModifiersModule.h"
// 標準機能をそのまま呼び出す版
// Build.cs に "AnimationModifiers"と"AnimationBlueprintLibrary"を要追加
// Editorモジュール
void UMyEditorBlueprintLibrary::ApplyAnimationModifiers(const TArray<UAnimSequence*>& InSequences)
{
if (IAnimationModifiersModule* Module = FModuleManager::Get().LoadModulePtr<IAnimationModifiersModule>("AnimationModifiers"))
{
Module->ApplyAnimationModifiers(InSequences);
}
}
これで問題ないのですが、↑だと細かい調整(特定のModifierだけ実行したいなど)ができないので、もう少しカスタマイズしたい人向け版のも貼っておきます。
// もう少しカスタマイズしたい人向け版
// 実行するModifierをクラスでフィルタリングできるようにした例
bool UMyEditorBlueprintLibrary::ApplyAnimationModifier(UAnimationAsset* InAnimationAsset, TSubclassOf<UAnimationModifier> InAnimModifierClass)
{
if(!InAnimationAsset)
{
return false;
}
UAnimSequence* AnimSequence = Cast<UAnimSequence>(InAnimationAsset);
if(!AnimSequence)
{
// AnimModifier can only be applied to AnimSequence at this time
return false;
}
const UAnimationModifiersAssetUserData* ModifiersData = InAnimationAsset->GetAssetUserData<UAnimationModifiersAssetUserData>();
if(!ModifiersData)
{
return false;
}
const TArray<UAnimationModifier*>& Modifiers = ModifiersData->GetAnimationModifierInstances();
for (UAnimationModifier* Modifier : Modifiers)
{
if(Modifier->GetClass() == InAnimModifierClass)
{
// すでに最新版のModifierを適応済みならスキップ
if(!Modifier->IsLatestRevisionApplied())
{
Modifier->ApplyToAnimationSequence(AnimSequence);
}
}
}
return true;
}
これでBPからAnimation Modifierを実行できるようになりました。あとは用途に応じてEditorUtilityWidget や Subsystemから呼び出せばOKです。
Animation Modifierを自動的に実行したい!
アニメーションアセットの(再)インポート時に実行したい!
Import Subsystemと先ほど追加したノードを併用することで実現可能です。こちらの記事に詳しくまとまっていますので、具体的な実装方法は割愛します。
アニメーションアセットの保存時など、とにかく何か変更があったら実行したい!
Editor Validator Subsystemと併用することで実現可能です。こちらも記事にまとまっていますので、実装の際は下記リンク先をご確認ください!
ただし、保存後に処理が走ったりDirtyフラグがついてしまうなどの問題があるので少し微妙かもです。
さいごに
かんたんな内容でしたが、ヒューマンエラーを可能な限り削減する上でこういった自動化は非常に重要になってきます!
めんどうな作業はガンガン自動化していきましょう!
おまけ:Animation Montageに対してもAnimation Modifierを使いたいんだけど?
UE-120734
[Feature Request] Refactor UAnimationBlueprintLibrary so animation modifiers can be used on montages
https://issues.unrealengine.com/issue/UE-120734
5.2で対応予定のようです…
おしまい