LoginSignup
4

More than 5 years have passed since last update.

アニメーションノードをまとめたアニメーションノードを作ってみた

Posted at

自作アニメーションノードをつくってみよう、その2です。その1はこちら

Transform(Modify) ノードに必要なノードをまとめてみる

今回は、アニムグラフで配置するノードを一つにまとめたノードを C++ で作ってみます。

まとめるノードはこちら。

  • LocalToComponent ノード
  • Transform(Modify) Bone ノード
  • ComponentToLocal ノード

アニムグラフで配置すると、このようになります。
node_combine.png

変更されていることがわかるように、Transform(Modify) Bone ノードでルートボーンを少しだけ上に上げてみます。
(変更するパラメータは赤枠で括っています。)

Anim Behavior ノードを用意する

では、Anim Behavior ノードを用意します。

今回も規模は大きくないので、ソースコードをそのまま載せます。

AnimNode_MyTransformBone.h
#pragma once

#include "Animation/AnimNodeBase.h"
#include "Animation/AnimNodeSpaceConversions.h"

#include "BoneControllers/AnimNode_ModifyBone.h"

#include "AnimNode_MyTransformBone.generated.h"


USTRUCT()
struct MYSANDBOX_API FAnimNode_MyTransformBone : public FAnimNode_Base
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Links)
    FPoseLink SourcePose;

public:
    FAnimNode_MyTransformBone();

    virtual void Initialize(const FAnimationInitializeContext& Context) override;
    virtual void CacheBones(const FAnimationCacheBonesContext& Context) override;
    virtual void Update(const FAnimationUpdateContext& Context) override;
    virtual void Evaluate(FPoseContext& Output) override;

private:
    FAnimNode_ConvertLocalToComponentSpace LocalToComponentNode;
    FAnimNode_ModifyBone ModifyBoneNode;
    FAnimNode_ConvertComponentToLocalSpace ComponentToLocalNode;

};
AnimNode_MyTransformBone.cpp
#include "MySandbox.h"
#include "AnimNode_MyTransformBone.h"

#include "Animation/AnimInstanceProxy.h"

// ----------------------------------------------------------------------------
FAnimNode_MyTransformBone::FAnimNode_MyTransformBone()
    : LocalToComponentNode()
    , ModifyBoneNode()
    , ComponentToLocalNode()
{
}

// ----------------------------------------------------------------------------
void FAnimNode_MyTransformBone::Initialize(const FAnimationInitializeContext& Context)
{
    FAnimNode_Base::Initialize(Context);

    // ノードやポーズを接続する
    ComponentToLocalNode.ComponentPose.SetLinkNode(&ModifyBoneNode);
    ModifyBoneNode.ComponentPose.SetLinkNode(&LocalToComponentNode);
    LocalToComponentNode.LocalPose = SourcePose;

    // Transform(Modify) Bone ノードでルートボーンを少しだけ上に上げる。
    ModifyBoneNode.BoneToModify.BoneName = FName("Root");
    ModifyBoneNode.BoneToModify.Initialize(Context.AnimInstanceProxy->GetSkeleton());
    ModifyBoneNode.Translation = FVector(0, 0, 100);
    ModifyBoneNode.TranslationMode = BMM_Replace;

    ComponentToLocalNode.Initialize(Context);
}

// ----------------------------------------------------------------------------
void FAnimNode_MyTransformBone::CacheBones(const FAnimationCacheBonesContext& Context)
{
    ComponentToLocalNode.CacheBones(Context);
}

// ----------------------------------------------------------------------------
void FAnimNode_MyTransformBone::Update(const FAnimationUpdateContext& Context)
{
    ComponentToLocalNode.Update(Context);
}

// ----------------------------------------------------------------------------
void FAnimNode_MyTransformBone::Evaluate(FPoseContext& Output)
{
    ComponentToLocalNode.Evaluate(Output);
}

今回は、FAnimNode_ModifyBone を内包しているため、以下のモジュールを「~.Build.cs」の「PublicDependencyModuleNames」に追加する必要があります。

  • AnimGraphRuntime

ノードとポーズを接続する

UE4 の 4.15 から FPoseLinkBase::SetLinkNode という関数が追加されました。
これは何なのか?というと、アニムグラフで言うところのポーズとノードを繋ぐ部分に相当します。

例えば、

    ModifyBoneNode.ComponentPose.SetLinkNode(&LocalToComponentNode);

これをアニムグラフで表現すると、以下のようになります。
node_combine2.png

今回の場合は、

    ComponentToLocalNode.ComponentPose.SetLinkNode(&ModifyBoneNode);
    ModifyBoneNode.ComponentPose.SetLinkNode(&LocalToComponentNode);

このように記述するだけで3つのノードをつなげたことになります。

入力ポーズを内包するノードに渡す

カスタムノードの入力ポーズを内包するノードに渡したい場合は、以下のようにポーズを代入してやります。

    LocalToComponentNode.LocalPose = SourcePose;

これは Initialize で一度代入すれば大丈夫です。

ルートノードの関数の呼び出しだけでカスタムノードを更新する

このようにノードやポーズをつなげた場合、ルートノード(アニムグラフで見て、一番最後に実行されるノード。今回の場合は ComponentToLocal ノード)の Initialize や Update、Evaluate を呼び出すだけで、繋がっている全ノードの処理が実行されます。

例えば、今回のカスタムノードの Evaluate はコレだけです。

void FAnimNode_MyTransformBone::Evaluate(FPoseContext& Output)
{
    ComponentToLocalNode.Evaluate(Output);
}

Anim Graph ノードを用意する

Anim Behavior ノードの用意が終わったら、Anim Graph ノードを用意します。
今回もタイトルを変えただけなので、ポーズを返すだけのノードと全く同じ構成です。

念のため、コードを載せておきます。

AnimGraphNode_MyTransformBone.h
#pragma once

#include "AnimGraphNode_Base.h"
#include "Animation/AnimNode/AnimNode_MyTransformBone.h"

#include "AnimGraphNode_MyTransformBone.generated.h"

UCLASS()
class UAnimGraphNode_MyTransformBone : public UAnimGraphNode_Base
{
    GENERATED_UCLASS_BODY()

    UPROPERTY(EditAnywhere, Category = Settings)
    FAnimNode_MyTransformBone Node;

public:
    virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;


};
AnimGraphNode_MyTransformBone.cpp
#include "MySandboxDeveloper.h"
#include "AnimGraphNode_MyTransformBone.h"

#define LOCTEXT_NAMESPACE "MySandboxDeveloper"

UAnimGraphNode_MyTransformBone::UAnimGraphNode_MyTransformBone(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
}

// ----------------------------------------------------------------------------
FText UAnimGraphNode_MyTransformBone::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
    return LOCTEXT("AnimGraphNode_MyTransformBone_Title", "My Transform Bone");
}

#undef LOCTEXT_NAMESPACE

UE4Editor で確認する

こうして出来上がったノードがこちらです。前回と同じく、引数は入力ポーズのみです。
node_combine3.png

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
4