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

More than 1 year has passed since last update.

自作アニメーションノードをつくってみよう、その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