目的:在AnimationBlueprint中使用自定义动画控制节点。

主要过程:

1.      引用相关模块。在Client.Build.cs文件中,PublicDependencyModuleNames.AddRange里加入”AnimGraphRuntime”,“AnimGraph”, “BlueprintGraph”,添加引用模块后可在使用时直接包含头文件名称,而不用指定具体路径。

2.      实现AnimNode类,用于处理更新骨骼位置等具体逻辑;

3.      实现AnimGraphNode类,用于在编辑器中显示信息等;

4.      编辑工程后即可在AnimationBlueprint中使用该节点


下面以我的自定义动画节点CopyParentBone为例,该节点作用是更改当前Component内某骨骼的Transform为Parent Component内同名称骨骼的Transform:

 

一、添加引用模块

Client.Build.cs

PublicDependencyModuleNames.AddRange(new string[] 
        { 
            "Core", 
			"CoreUObject", 
			"Engine", 
			"InputCore",
			"AIModule",
			"GameplayTasks",
            "Landscape",
            "Foliage",
            "AnimGraphRuntime",
            "AnimGraph",
            "BlueprintGraph"
        });


二、AnimNode类

Public/AnimNode_CopyParentBone.h


/*
 * \file AnimNode_CopyParentBone.h
 *
 * \author: Jia Zhipeng
 * \date: 2016/02/24 
 */

#pragma once
#include "AnimNode_SkeletalControlBase.h"
#include "AnimNode_CopyParentBone.generated.h"

USTRUCT()
struct FAnimNode_CopyParentBone :public FAnimNode_SkeletalControlBase
//父类可以是FAnimNode_SkeletalControlBase或者FAnimNode_Base
//FAnimNode_SkeletalControlBase一般用于对骨骼的控制,通过EvaluateBoneTransforms更改骨骼位置。
//FAnimNode_Base一般用于对整体MeshBase的更改,通过Evaluate或者EvaluateComponentSpace更改Output.Pose更改全身的位置
//自定义类继承父类后,override部分接口即可,以下是我用到的主要接口
{
	GENERATED_USTRUCT_BODY()

	/** Name of bone to control. **/
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SkeletalControl)
	FBoneReference BoneToModify;
	
public:
	//	Constructor
	FAnimNode_CopyParentBone();

// 	// FAnimNode_Base interface
//	显示Debug信息
 	virtual void GatherDebugData(FNodeDebugData& DebugData) override;
// 	// End of FAnimNode_Base interface

	// FAnimNode_SkeletalControlBase interface
//	更改位置的逻辑实现函数
	virtual void EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms) override;
//	判断用到的骨骼是否有效	
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;
	// End of FAnimNode_SkeletalControlBase interface

private:
	// FAnimNode_SkeletalControlBase interface
//	初始化骨骼引用
	virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
	// End of FAnimNode_SkeletalControlBase interface
};

Private/AnimNode_CopyParentBone.cpp

/*
 * \file AnimNode_CopyParentBone.cpp
 *
 * \author: Jia Zhipeng
 * \date: 2016/02/24 
 */

#include "Client.h"//自己的Game.h
#include "AnimNode_CopyParentBone.h"

FAnimNode_CopyParentBone::FAnimNode_CopyParentBone()
{
	
}

//控制骨骼运动的逻辑实现。在OutBoneTransforms里Add需要修改的BoneTransform
void FAnimNode_CopyParentBone::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
	check(OutBoneTransforms.Num() == 0);
	FTransform NewBoneTM = FTransform::Identity;
	const FBoneContainer BoneContainer = MeshBases.GetPose().GetBoneContainer();
	
	USceneComponent* ParentComponent = SkelComp->GetAttachParent();
	if (ParentComponent)
		NewBoneTM = ParentComponent->GetSocketTransform(BoneToModify.BoneName, RTS_Component);
	else
	{
		UE_LOG(LogAnimation, Warning, TEXT("FAnimNode_CopyParentBone cannot get parent component"));
	}
	OutBoneTransforms.Add(FBoneTransform(BoneToModify.GetCompactPoseIndex(BoneContainer), NewBoneTM));
}

void FAnimNode_CopyParentBone::GatherDebugData(FNodeDebugData& DebugData)
{
	FString DebugLine = DebugData.GetNodeName(this);

	DebugLine += "(";
	AddDebugNodeData(DebugLine);
	DebugLine += FString::Printf(TEXT(" Target: %s)"), * BoneToModify.BoneName.ToString());
	DebugData.AddDebugItem(DebugLine);

	ComponentPose.GatherDebugData(DebugData);
}

bool FAnimNode_CopyParentBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
{
	return (BoneToModify.IsValid(RequiredBones));
}

void FAnimNode_CopyParentBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)
{
	BoneToModify.Initialize(RequiredBones);
}


三、AnimGraphNode

Public/AnimGraphNode_CopyParentBone.h

/*
 * \file AnimGraphNode_CopyParentBone.h
 *
 * \author: Jia Zhipeng
 * \date: 2016/02/24
 * \purporse: 自定义动画节点,在Parent Component中获得与当前Component的根骨骼同名的骨骼Transform,然后设置为当前骨骼的Transform
 */
#pragma once
#include "AnimGraphNode_SkeletalControlBase.h"
#include "AnimNode_CopyParentBone.h"
#include "AnimGraphNode_CopyParentBone.generated.h"

UCLASS(MinimalAPI)
class UAnimGraphNode_CopyParentBone : public UAnimGraphNode_SkeletalControlBase
{
	GENERATED_UCLASS_BODY()

	UPROPERTY(EditAnywhere, Category=Settings)
	FAnimNode_CopyParentBone Node;

	// UEdGraphNode interface
//	鼠标悬浮在Node上的提示文本
	virtual FText GetTooltipText() const override;
//	Node的名字文本	
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
	// End of UEdGraphNode interface

protected:
	// UAnimGraphNode_SkeletalControlBase interface
//	返回controller的描述
	virtual FText GetControllerDescription() const override;
//	返回引用的AnimNode
	virtual const FAnimNode_SkeletalControlBase* GetNode() const override { return &Node; }
	// End of UAnimGraphNode_SkeletalControlBase interface
	
};

Private/AnimGraphNode_CopyParenBone.cpp

/*
 * \file AnimNode_CopyParentBone.cpp
 *
 * \author: Jia Zhipeng
 * \date: 2016/02/24 
 */

#include "Client.h"
#include "AnimGraphNode_CopyParentBone.h"

#define LOCTEXT_NAMESPACE "A3Nodes"
UAnimGraphNode_CopyParentBone::UAnimGraphNode_CopyParentBone(const FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer)
{
}

FText UAnimGraphNode_CopyParentBone::GetTooltipText() const
{
	return LOCTEXT("AnimGraphNode_CopyParentBone_Tooltip", "Copy parent bone's transform to this component's root. Their names must be same");
}

FText UAnimGraphNode_CopyParentBone::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	return LOCTEXT("AnimGraphNode_CopyParentBone_Title", "Copy Parent Bone");
}

FText UAnimGraphNode_CopyParentBone::GetControllerDescription() const
{
	return LOCTEXT("CopyParentBone", "Copy Parent Bone");
}

#undef LOCTEXT_NAMESPACE


参考内容

1.Animation Node, Entire Source for a TurnIn Place Node

https://wiki.unrealengine.com/Animation_Node,_Entire_Source_for_a_Turn_In_Place_Node

2. 创建自定义动画节点

https://www.unrealengine.com/zh-CN/blog/creating-custom-animation-nodes

3.UE引擎中部分节点如AnimNode_CopyBone,AnimNode_ModifyBone的源代码




posted on 2016-02-24 20:31  Corgi  阅读(2620)  评论(0编辑  收藏  举报