UE5新建动画蓝图节点

巨坑无比,东西比较杂,凑合看吧

 这是我的目录结构,分为俩模块,一个伴随打包,一个只在编辑器阶段存在

 

"Modules": [
		{
			"Name": "AnimCsv",
			"Type": "Runtime",
			"LoadingPhase": "PreDefault"
		},
		{
			"Name": "AnimCsvEditor",
			"Type": "UncookedOnly",
			"LoadingPhase": "PreDefault"
		}
	]

注意看我模块的Type,不写UncookedOnly而是Editor会报错的

AnimCsvEditor模块需要自己建

1、新建文件夹AnimCsvEditor,以及里面的Private和Public子文件夹

2、从别的地方复制Build.cs改个名字叫XXXEditor.Build.cs

3、看代码

// Copyright 2021 - Michal Smoleň

using UnrealBuildTool;

public class AnimCsvEditor : ModuleRules
{
	public AnimCsvEditor(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicIncludePaths.AddRange(
			new string[] {
				// ... add public include paths required here ...
			}
			);
				
		
		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				// ... add other public dependencies that you statically link with here ...
				"AnimCsv"
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				"CoreUObject",
				"Slate",
				"SlateCore",
				"Engine",
				"InputCore",
				"UnrealEd",
				"AnimGraph",
				"BlueprintGraph",
				"AnimGraphRuntime",
				
				// ... add private dependencies that you statically link with here ...	
			}
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);
	}
}

该有的模块一定要有,尤其是AnimGraph、BlueprintGraph、AnimGraphRuntime这些

记得改类名,因为你是复制的文件嘛,改成你的模块名

(xxx未找到符号什么的就是因为缺少模块)

4、新建这俩文件,命名也是跟模块名一样

 里面的内容可以参考别的模块,类名字一定要改对

尤其是上图最后一行白色的,忘记改的话非常蛋疼!!!

总值名字千万不能错

5、 在引擎里给这编辑器模块加个类,继承自UAnimGraphNode_Base

(这是节点基类,不要继承他的子类,引擎不让你继承)

(这个类只是显示用的,实际的逻辑不在这里)

 注意看class旁边的ANIMCSVEDITOR_API,有这种什么什么API的类才让你继承,没有的说明是引擎内部类,你在别的模块无法继承

6、看代码,这是头文件,你的应该会自己生成

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "AnimGraphNode_Base.h"
//#include "AnimGraphNode_ModifyCurve.h"
#include "EdGraph/EdGraphNode.h"
//#include "AnimNodes/AnimNode_ModifyCurve.h"
#include "AnimNode_Demo.h"
#include "AnimGraphNode_Demo.generated.h"


/**
 * 
 */
UCLASS()
class ANIMCSVEDITOR_API UAnimGraphNode_Demo : public UAnimGraphNode_Base
{
	GENERATED_BODY()
	

	UPROPERTY(EditAnywhere, Category = Settings)
	FMotionMatchingStruct Node;

public:
	UAnimGraphNode_Demo();

	// UEdGraphNode interface
	virtual FText GetTooltipText() const override;
	virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
	// End of UEdGraphNode interface

	// UAnimGraphNode_Base interface
	virtual FString GetNodeCategory() const override;

};

 FMotionMatchingStruct这个属性是我自己建的,先不用管

就记住这玩意才是真正运行逻辑的地方,以上这部分代码只是用来显示用的

7、看代码,这个是cpp,上面的头文件实现部分

// Fill out your copyright notice in the Description page of Project Settings.


#include "AnimGraphNode_Demo.h"

#define LOCTEXT_NAMESPACE "AnimGraphNode_Demo"

UAnimGraphNode_Demo::UAnimGraphNode_Demo() 
{
}

FString UAnimGraphNode_Demo::GetNodeCategory() const
{
	return TEXT("Skeletal Control Nodes");
}

FText UAnimGraphNode_Demo::GetTooltipText() const
{
	return GetNodeTitle(ENodeTitleType::ListView);
}

FText UAnimGraphNode_Demo::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	return LOCTEXT("AnimGraphNode_ModifyCurve_Title", "Modify Curve");
}




#undef LOCTEXT_NAMESPACE

这里没啥好主意的,名字别搞错就行了。这样我们就创建好了XXXEditor模块。

下面才是节点的逻辑部分,也就是我们的AnimCsv模块,而不是AnimCsvEditor模块

Build.cs和之前的差不多

 

 然后这里说一下重点!!!!

你的FMotionMatchingStruct也就是你的节点逻辑类,无法从引擎创建,所以你得自己添加头文件和cpp文件,并自己继承

这个时候你可以选择FAnimNode_ModifyCurve(曲线节点)或其他类或基类都可以

先给大家看一下节点逻辑代码

#pragma once

#include "CoreMinimal.h"
#include "LoadCsvFile.h"
#include "AnimNodes/AnimNode_ModifyCurve.h"
#include "Math/UnrealMathUtility.h"
#include "AnimNode_Demo.generated.h"


USTRUCT(BlueprintType)
struct ANIMCSV_API FMotionMatchingStruct : public FAnimNode_ModifyCurve
{
	GENERATED_BODY()
public:
	FMotionMatchingStruct();

	//面捕数据
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = ModifyCurve, meta = (PinShownByDefault))
	FMyStructs FaceData;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = ModifyCurve, meta = (PinShownByDefault))
	FMyDeformerNameStructs Names;

	//播放动画的进度
	int PlayValue = 0;

	virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override;
	virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override;
};

 可以看到,你需要继承实现几个虚函数,Initialize_AnyThread或Update_AnyThread,当然你不需要也可以不继承,这里我是需要的,初始化和tick更新

然后就是实现部分,看代码。这里我省略了我读取CSV文件的逻辑,因为这不是本章的重点。

你肯定也要自己写自己的逻辑来弄动画节点吧

#include "AnimNode_Demo.h"

FMotionMatchingStruct::FMotionMatchingStruct()
{
	
}

void FMotionMatchingStruct::Initialize_AnyThread(const FAnimationInitializeContext& Context)
{
	Super::Initialize_AnyThread(Context);
	PlayValue = 0;
	for (FName val : Names.name)
	{
		CurveValues.Add(0.0);
		CurveNames.Add(val);
		UE_LOG(LogTemp, Warning, TEXT("FMotionMatchingStruct CurveNames:%s"), *val.ToString());
	}
	UE_LOG(LogTemp, Warning, TEXT("FMotionMatchingStruct CurveNames length:%d"), Names.name.Num());
}

void FMotionMatchingStruct::Update_AnyThread(const FAnimationUpdateContext& Context)
{
	Super::Update_AnyThread(Context);
	//取出播放一帧数据
	if(FaceData.test.Num() > 0)
	{
		const int FaceDataNum = FaceData.test.Num();
        if(FaceDataNum > PlayValue)
        {
        	//UE_LOG(LogTemp, Warning, TEXT("FMotionMatchingStruct FaceDataNum length:%d , PlayValue :%d"), FaceDataNum,PlayValue);
        	TArray<FString> facedata_strings = FaceData.test[PlayValue].test;//获取一帧的数据
        	for(int i=0; i<CurveNames.Num(); i++)
        	{
        		const int num = Names.data_num[i];//找出这个形态键对应着数据的第几个索引
        		if(facedata_strings.Num() > num)
        		{
        			UE_LOG(LogTemp, Warning, TEXT("FMotionMatchingStruct facedata_strings:%s"), *facedata_strings[num]);
        			CurveValues[i] = FMath::Clamp(FCString::Atof(*facedata_strings[num]),0.0f,1.0f);
        		}
        	}
        }
        else
        {
        	PlayValue = 0;
        }
        PlayValue++;
	}
	
}

有条件的顺着引擎看看源代码,可以学一下人家是咋写的

完整的代码我在码云开源了

Face UE5: ue5用的人脸面部捕捉,不需要使用苹果手机 支持VRoid 的vrm模型 (gitee.com)

视频我已经删了,因为找到了更好的面捕,就不需要这个之前写的了

不过可以学习一下怎么创建动画蓝图节点

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值