やりたいこと
- ルートモーションを使いたい。
- だが、Character Actorクラス+Character Movement Componentで作るほど大げさにはしたくない。
- 普通のActor (またはPawn)+Skeletal Mesh Componentでサクっとやりたい。
- Blueprint で使えるノードが欲しい。
…をやるときに使える便利関数のメモ。
参考サイト
UE4ルートモーションについてのメモ を参考にさせていただきました。
UAnimInstance::ConsumeExtractedRootMotion() について
上記の参考サイトの通り、Character Movement Componentを使用しないとルートモーションは適用されず、UAnimInstance::ConsumeExtractedRootMotion()を使って得られたTransformを、自前でアクタのTransformに作用させなくてはならない。
ところが、UAnimInstance::ConsumeExtractedRootMotion()から返ってくるのは、Component SpaceでのDelta Transformであり、アクタのTransformに直接作用させるにはひと手間必要となる。
Character Movement Componentのエンジンソースを辿って、便利関数を見つけたのでメモとして残しておく。
USkeletalMeshComponent::ConvertLocalRootMotionToWorld()
USkeletalMeshComponent::ConvertLocalRootMotionToWorld()がその便利関数である。
この関数は、UAnimInstance::ConsumeExtractedRootMotion()の結果(Component SpaceでのDelta Transform)を与えると、World SpaceでのDelta Transformに変換してくれる。
C++ソース例
UAnimInstanceを継承したクラスを用意する。
例)URootMotionAnimInstance
RootMotionAnimInstance.h
以下のヘッダファイルを見ての通り、ConsumeExtractedRootMotion()
をBlueprintに公開するのが目的である。
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "RootMotionAnimInstance.generated.h"
// Custom UAnimInstance class which have an utility to extract its root motion.
UCLASS(transient)
class ROOTMOTIONTEST_API URootMotionAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
// Get current accumulated root motion, removing it from the AnimInstance in the process.
// This function is only for exposing UAnimInstance::ConsumeExtractedRootMotion() to the Blueprint.
UFUNCTION(BlueprintCallable, Category = "Root Motion Anim Instance",
meta = (InAlpha = "1"))
void ConsumeExtractedRootMotion(float InAlpha, bool& OutSuccess, FTransform& OutDeltaTransformInWorld);
};
RootMotionAnimInstance.cpp
ここでは、UAnimInstance::ConsumeExtractedRootMotion()で取得したDelta Transformを、USkeletalMeshComponent::ConvertLocalRootMotionToWorld()でWorld系に変換して返している。
#include "RootMotionAnimInstance.h"
void URootMotionAnimInstance::ConsumeExtractedRootMotion(float InAlpha,
bool& OutSuccess, FTransform& OutDeltaTransformInWorld)
{
USkeletalMeshComponent* SkelComp = GetOwningComponent();
FRootMotionMovementParams Params = UAnimInstance::ConsumeExtractedRootMotion(InAlpha);
if (SkelComp != nullptr && Params.bHasRootMotion)
{
OutSuccess = true;
OutDeltaTransformInWorld =
SkelComp->ConvertLocalRootMotionToWorld(Params.GetRootMotionTransform());
}
else
{
OutSuccess = false;
OutDeltaTransformInWorld.SetIdentity();
}
}
Blueprintでの使用例
Pawnを継承したクラスBP_RootMotion_Pawnを作成。
試していないが、素のActorを継承したクラスでも大丈夫なはず。
Componentsタブ
Event Tick
C++側でWorld系のDelta Transformに変換済みなので、シンプルにAddActorWorldTransform
に渡すだけ。
実行例
一応、ワールド原点から外した位置・角度で動作をさせている。
なお、使用したアニメーションは2021年9月の無料マーケットプレイスコンテンツのClose Combat Animsetのもの。