UE4にて選んだアニメーションシーケンスの全てに通知を追加する。
通知するフレームはアニメーションが99%終了時点。
UE4でアニメーションの終了を感知してタスクを進めてみたいから。
(モンタージュファイルなら終了を検知できるとか言うな)
コードは最後に貼ってあります
C++でプロジェクトを作る。
ブループリント→クラス→下のコードで作ったBP_AnimNotifyAdderを作る。
続いてC++のコードを実行してくれるメニューボタン的なのを作ってくれる『ウィジット』を作る。
ウィジットちゃんの中身。
最初に開いたときには『デザイナー』のタブになってると思うので、
そこでボタンButtonを画面に配置しましょう。したらば、ON_Clickイベントを追加する項目があるはずなので追加しましょう。
(グレーのボタンを選択して、右下の緑色のやつを押す)
次はアニメーションシーケンス用の変数の配列『Animation』を作ってやり、その中に通知キーを打ちたいアニメーションファイルをぶち込む
(右下はグレイマンのアニメ)
そしたらレベルブループリントを開く。
プレイしたときにウィジットのメニューが出るようにする。
プレイ画面
(左上の■ボタンを押すと変換開始)
これでアニメーションファイルの最後らへんに一括でキーを打てた。
ファイル自体は複製されます。
以下コード。
プロジェクト名は『KA_EUW_CallBP』
キンアジ氏のブログでやってたことを試したプロジェクトの流用だって言わなきゃバレへんか…
ヘッダーファイル
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "UAnimNotifyAdder.generated.h"
class UAnimSequence;
/**
* 下の~APIはちゃんとプロジェクト名ごとに変えてね
*/
UCLASS(Blueprintable)
class KA_EUW_CALLBP_API UAnimNotifyAdder : public UObject
{
GENERATED_BODY()
public:
/** 複数のアニメーションに通知を追加して保存する */
UFUNCTION(BlueprintCallable, Category = "Animation")
void AddNotifyAndSave(const TArray<UAnimSequence*>& AnimSequences);
};
ソースファイル
#include "UAnimNotifyAdder.h"
#include "Animation/AnimSequence.h"
#include "Animation/AnimNotifies/AnimNotify.h"
#include "AssetRegistryModule.h"
#include "Misc/PackageName.h"
#include "UObject/Package.h"
void UAnimNotifyAdder::AddNotifyAndSave(const TArray<UAnimSequence*>& AnimSequences)
{
UE_LOG(LogTemp, Warning, TEXT("AddNotifyAndSave called with %d sequences"), AnimSequences.Num());
for (UAnimSequence* AnimSequence : AnimSequences)
{
if (!IsValid(AnimSequence))
{
UE_LOG(LogTemp, Warning, TEXT("Invalid AnimSequence skipped"));
continue;
}
if (AnimSequence->GetLinker() == nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("AnimSequence %s is not fully loaded, skipping"), *AnimSequence->GetName());
continue;
}
// 保存用パッケージ作成
FString AssetName = AnimSequence->GetName() + TEXT("_Notified");
FString PackagePath = TEXT("/Game/ModifiedAnimations/") + AssetName;
UPackage* Package = CreatePackage(*PackagePath);
if (!IsValid(Package))
{
UE_LOG(LogTemp, Error, TEXT("Failed to create package for %s"), *AssetName);
continue;
}
Package->FullyLoad();
// アニメーションを複製
UAnimSequence* NewAsset = DuplicateObject<UAnimSequence>(AnimSequence, Package, FName(*AssetName));
if (!IsValid(NewAsset))
{
UE_LOG(LogTemp, Error, TEXT("Failed to duplicate AnimSequence %s"), *AnimSequence->GetName());
continue;
}
// 通知オブジェクトを NewAsset に属する形で生成(RF_Transactional 付き)
UAnimNotify* NotifyObj = NewObject<UAnimNotify>(NewAsset, UAnimNotify::StaticClass(), NAME_None, RF_Transactional);
if (!IsValid(NotifyObj))
{
UE_LOG(LogTemp, Error, TEXT("Failed to create generic NotifyObj"));
continue;
}
// 通知イベント作成(構造を完全初期化)
float NotifyTime = NewAsset->SequenceLength * 0.99f;
FAnimNotifyEvent NewNotify;
NewNotify.Notify = NotifyObj;
NewNotify.NotifyName = FName("EndAnim");
NewNotify.NotifyTriggerChance = 1.0f;
NewNotify.NotifyFilterType = ENotifyFilterType::NoFiltering;
NewNotify.NotifyFilterLOD = 0;
NewNotify.TriggerWeightThreshold = 0.0f;
NewNotify.TrackIndex = 0;
// 通知時間を安全に設定(正しい型で)
NewNotify.SetTime(NotifyTime, EAnimLinkMethod::Absolute);
// 通知追加
NewAsset->Modify();
NewAsset->Notifies.Add(NewNotify);
// アセット登録と保存準備
FAssetRegistryModule::AssetCreated(NewAsset);
NewAsset->PostEditChange();
NewAsset->MarkPackageDirty();
FString FilePath = FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetAssetPackageExtension());
UE_LOG(LogTemp, Warning, TEXT("Saving to: %s"), *FilePath);
UE_LOG(LogTemp, Warning, TEXT("Added notify 'EndAnim' at %.2f to %s"), NotifyTime, *NewAsset->GetName());
UPackage::SavePackage(Package, NewAsset, EObjectFlags::RF_Public | RF_Standalone, *FilePath);
}
}
Build.cs
モジュールを色々突っ込んでますが何がどんな機能を提供してるかは知らない
でもないと動かない
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class KA_EUW_CallBP : ModuleRules
{
public KA_EUW_CallBP(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "LevelEditor", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "Slate", "SlateCore", "UnrealEd", "Blutility", "UMG", "UMGEditor", "AnimGraph" });
}
}
実はUnityでC#使ってたけどC++なんぞ1ミリも分からないがAI虐めながら書きました。
AIも全く完璧じゃないので間違えまくりエラー吐きまくりの中ちゃんとテストして動いたので動作はします。