LoginSignup
7
2

More than 1 year has passed since last update.

【UE4】Character Movement Componentを使わずにルートモーションをする

Posted at

やりたいこと

  • ルートモーションを使いたい。
  • だが、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に公開するのが目的である。

RootMotionAnimInstance.h
#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系に変換して返している。

RootMotionAnimInstance.cpp
#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タブ

Characterクラスに比べて非常にシンプルに組める。
image.png

Event Tick

C++側でWorld系のDelta Transformに変換済みなので、シンプルにAddActorWorldTransformに渡すだけ。
image.png

実行例

20210917_01_RootMotionInPawn.gif

一応、ワールド原点から外した位置・角度で動作をさせている。

なお、使用したアニメーションは2021年9月の無料マーケットプレイスコンテンツClose Combat Animsetのもの。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2