目的:在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的源代码

[UE4]CustomAnimationBlueprintNode 自定义动画蓝图节点的更多相关文章

  1. [UE4]角色、动画蓝图、动画蒙太奇、动画之间的调用关系

    一.在“角色”中设置要使用的“动画蓝图” 二.在“动画蓝图”中使用“动画”和“混合动画” 三.在“混合动画”中,也可以使用“动画” 四.在角色中使用“动画蒙太奇”

  2. (原)Unreal源码搬山-动画篇 自定义动画节点(一)

    @author:黑袍小道 太忙了,来更新下,嘿嘿 前言: 本文是接着上文 Unreal搬山之动画模块_Unreal动画流程和框架,进行简单入门如何自定义动画图标的AnimNode. 正文: 一.Ani ...

  3. 【UE4 C++】Tick的三种方式、异步蓝图节点

    Tick的三种方式 包括 默认 Tick (Actor.Component.UMG) TimerManager 定时器 FTickableGameObject 可以写原生 Object 也可以继承UO ...

  4. ue4动画蓝图

    动画资源 animation sequence  序列动画 :一帧一骨骼 montage   片断动画 : 动画蒙太奇   将不同的片断组成一个动画 blend space    混合动画  : 将2 ...

  5. [UE4]蓝图节点的组织

    1.将选择的多个蓝图节点变成一个节点,可以给这个节点命名:还可以随时展开这个节点 2.也可以将选中的蓝图节点转换成一个函数或者一个宏.当然也是可以随时展开成原来的样子. 3.变成节点的话,会生成一个子 ...

  6. UE4]不使用角色蓝图、动画蓝图、状态机,用“24K纯C++”实现动画播放

    http://aigo.iteye.com/blog/2283454 原文作者:@玄冬Wong 不好意思,我稍稍标题党了,目前还不清楚如何用C++代码来实现BlendSpace和Montage的逻辑, ...

  7. python全栈开发day48-jqurey自定义动画,jQuery属性操作,jQuery的文档操作,jQuery中的ajax

    一.昨日内容回顾 1.jQuery初识 1).使用jQuery而非JS的六大理由 2).jQuery对象和js对象转换 3).jQuery的两大特点 4).jQuery的入口函数三大写法 5).jQu ...

  8. android 自定义动画

    android自定义动画注意是继承Animation,重写里面的initialize和applyTransformation,在initialize方法做一些初始化的工作,在applyTransfor ...

  9. Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析

    这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...

随机推荐

  1. Java线程的5个使用技巧

    萝卜白菜各有所爱.像小编我就喜欢Java.学无止境,这也是我喜欢它的一个原因.日常工作中你所用到的工具,通常都有些你从来没有了解过的东西,比方说某个方法或者是一些有趣的用法.比如说线程.没错,就是线程 ...

  2. iOS中的上传、下载流程心得

    访问相册 1.  判断资源库是否有效 2.  创建imagePickerController 设置代理 弹出视图控制器 3.  实现协议方法 > iOS10 访问系统相册需要在info.plis ...

  3. HTML页面弹出自定义对话框带遮蔽罩(使用JavaScript)

    转载:http://blog.sina.com.cn/s/blog_610f47c50100ohe4.html 原理其实很简单:首先绘制弹出的自定义对话框,将其使用display:none隐藏,因为设 ...

  4. js 事件绑定

    事件绑定的方式 1.  DOM  元素行内绑定 <div onclick="alert(1)"></div>   2. js on+eventType do ...

  5. .Net判断一个对象是否为数值类型探讨总结(高营养含量,含最终代码及跑分)

    前一篇发出来后引发了积极的探讨,起到了抛砖引玉效果,感谢大家参与. 吐槽一下:这个问题比其看起来要难得多得多啊. 大家的讨论最终还是没有一个完全正确的答案,不过我根据讨论结果总结了一个差不多算是最终版 ...

  6. MVC中使用EF:排序,过滤,分页

    原文链接:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging ...

  7. SQL Server已提交读快照隔离级别的设置

    如果要把SQL Server数据库事务隔离级别设置为已提交读快照隔离 如果直接运行下面的语句: ALTER Database [mydbname] SET READ_COMMITTED_SNAPSHO ...

  8. net软件自动生成开发编程框架编程机器人

    有一个.net自动生成平台(编程机器人)推荐给大家,常规几天十几天的工作,机器人几分钟搞定,不写一行代码,留下大把休闲时光,适应于聪明人:不想太累的程序员(看看风景泡泡妞),不想多请人的老板(有限资金 ...

  9. Web程序的运行原理及流程(二)

    其实WEB服务器和WEB应用服务器这两个概念特别容易混淆  可以理解为装了不同软件(服务)的两台计算机(服务器)吧 先对两个概念做一个简单介绍 了解了基本的概念 我们再用两个典型的例子做一下比较(建立 ...

  10. Linux(Ubuntu 14.0)

    开始了Mono的学习.学习了Mono for Android之后,编译一些小的APK,总发现这些APK文件很大,额,真心不知道为什么,那么,就让我们从头开始学期了,Android是基于Linux的,那 ...