UE4 创建自定义动画节点

article/2025/10/8 14:05:01

创建自定义动画节点需要两个类:

一个是您在编辑器中看到的图表节点

一个是真正在运行时工作的行为节点

 

动画图表节点,派生自:UAnimGraphNode_Base

例如:class UAnimGraphNode_SequencePlayer : public UAnimGraphNode_Base

 

动画行为节点,派生自:FAnimNode_Base

例如:struct ENGINE_API FAnimNode_SequencePlayer : public FAnimNode_Base

 

两个节点的基类是不同的:一个基类是UObject(UAnimGraphNode_Base),另一个的基类是UStruct(FAnimNode_Base)

 

动画图表节点类的构建:

所有的图表节点包含了类似这样的对应行为节点:

 

class UAnimGraphNode_SequencePlayer : public UAnimGraphNode_Base

{

    GENERATED_BODY()

    UPROPERTY(EditAnywhere, Category=Settings)

    FAnimNode_SequencePlayer Node;

}

 

这就是最简单的 动画图表节点,其中包含动作行为节点对象。 

动画行为节点的执行,是通过FPoseLink或FComponentSpacePoseLink进行串联的。

 

FPoseLink 是本地骨骼空间的(其实是相对于父节点来说的), FComponetSpacePoseLink是控件空间的。

 

动画图表节点默认带有FPoseLink输出(也就是右侧的小人, 如果需要改变成FComponetSpacePoseLink, 需要重写CreateOutputPins,其中调用CreatePin。

 

virtual void CreateOutputPins() override;

void UAnimGraphNode_LocalToComponentSpace::CreateOutputPins()

{

       CreatePin(EGPD_Output, UAnimationGraphSchema::PC_Struct,  FComponentSpacePoseLink::StaticStruct(), TEXT("ComponentPose"));

}

 

 

动画行为节点类的构建

让我们看下FAnimNode_Base节点:

struct ENGINE_API FAnimNode_Base

{

    // Interface to implement,这就是你在你的动画行为节点中应该重写的几个函数

    virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) {}

    virtual void Update_AnyThread(const FAnimationUpdateContext& Context) {}

    virtual void Evaluate_AnyThread(FPoseContext& Output) { check(false); }

    virtual void EvaluateComponentSpace_AnyThread(FComponentSpacePoseContext& Output) { check(false); }

    virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {}

    virtual void GatherDebugData(FNodeDebugData& DebugData){}

};

有三个决定了您的节点如何表现的主要函数。它们是Initialize_AnyThread、Update_AnyThread和Evaluate_AnyThread,这里是对它们应用的简单描述:

  • Initialize_AnyThread - 任何时候当您需要进行初始化或重新初始化时调用该函数(当修改实例的网格物体时)。

  • Update_AnyThread - 调用该函数来更新当前状态(比如更新播放时间或混合权重)。该函数取入一个FAnimationUpdateContext,它知道更新的DeltaTime和当前的节点混合权重。

  • Evaluate_AnyThread - 调用该函数来生成一个‘姿势’(一系列的骨骼变换)。//当动画图表节点的输出是FPoseLink时,执行的是该函数, 如果是FComponetSpacePoseLink,执行的应该是EvaluateComponentSpace_AnyThread

  • EvaluateComponentSpace_AnyThread- 调用该函数来生成一个‘姿势’(一系列的骨骼变换)

最重要的就是Evaluate_AnyThreadEvaluateComponentSpace_AnyThread,其中最终的操作是骨骼变换的设置。

void FAnimNode_MYAnimNode::Evaluate_AnyThread(FPoseContext & Output){FName BoneName(TEXT("boneName"));//Output.Pose.GetBoneContainer()返回的FBoneContainer中,包含有当前网格体用到的骨架的引用,以及当前网格体用到的骨架中的真正用到的骨骼的索引数组。索引数组包含骨架的部分或全部。//OutPut.Pose中包含用到的骨骼的变换数组,骨骼变换数组与FBoneContainer中的索引数组相互对应。//GetPoseBoneIndexForBoneName是根据骨骼名称,获取骨骼的索引int32 MeshIndex = Output.Pose.GetBoneContainer().GetPoseBoneIndexForBoneName(BoneName);if (MeshIndex != INDEX_NONE){//MakeCompactPoseIndex 是根据骨骼的索引,找到骨骼索引在索引数组的位置,也就是OutPut.Pose中对应骨骼变化的变换数组的位置。FCompactPoseBoneIndex CPIndex = Output.Pose.GetBoneContainer().MakeCompactPoseIndex(FMeshPoseBoneIndex(MeshIndex));if (CPIndex != INDEX_NONE){FTransform boneTransfrom(FRotator(0.0f, 0.0f, 90.0f));Output.Pose[CPIndex] = boneTransfrom;}}//注意这时候当output.IsNormalized()返回false, Output.ContainsNaN() 返回true,这时候表示没有正确设置。尤其是当该节点与使用AnimNode_SaveCachePose一起使用,output传进来时,所有骨骼都没有设置正确的变换,这时候可以使用Output.ResetToRefPose(),将所有骨骼变换设置为参考姿势。}

 

 

 

在这些基本函数的基础上,您需要提供两个函数的实现,以确保您的节点可以正常同图表的其他部分协同工作

virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) {}

virtual void GatherDebugData(FNodeDebugData& DebugData){}

CacheBones_AnyThread用于刷新该节点所引用的骨骼索引,GatherDebugData用于使用"ShowDebug Animation"数据进行调试。为了保持到子项的连接,使用这些是很重要的。

FPoseLink 应该调用它下面的所有节点,以确保您的节点连接的任何姿势连接都会被调用。知道FPoseLink如何工作非常重要,因为任何时候当您调用任何动画函数时,您也必须调用该Pose函数。比如在您的Update_AnyThread函数中您应该调用BasePose->Update。同样,如果您有BasePose作为成员变量,您也应该在CacheBones_AnyThread函数中调用BasePose->CacheBones。(调用FPoseLink的对应函数,FPoseLink会找到它所连接的上一个节点,然后执行上一个节点的对应函数,节点对应函数调用的次序有点类似于递归,从最终动画姿势开始,一直到最开始,见下图)

请参照该示例:

 

void FAnimNode_BlendListBase::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context)

{

    for(int32 ChildIndex=0; ChildIndex<BlendPose.Num(); ChildIndex++)

    {

        BlendPose[ChildIndex].CacheBones(Context);

    }

}

 

 

 

void FAnimNode_BlendListBase::Evaluate_AnyThread(FPoseContext& Output)

{

。。。

              for (int32 i = 0; i < PosesToEvaluate.Num(); ++i)

              {

                     int32 PoseIndex = PosesToEvaluate[i];

                     FPoseContext EvaluateContext(Output);

                     FPoseLink& CurrentPose = BlendPose[PoseIndex];

                     CurrentPose.Evaluate(EvaluateContext);

                     FilteredPoses[i].MoveBonesFrom(EvaluateContext.Pose);

                     FilteredCurve[i].MoveFrom(EvaluateContext.Curve);

              }

。。。

}

 

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

 


http://chatgpt.dhexx.cn/article/QiogcCK7.shtml

相关文章

ViewPager2添加自定义动画

此篇为ViewPager2的拓展篇&#xff0c;具体可查看ViewPager2的使用 ViewPager2自定义动画的核心是使用PageTransformer来实现&#xff0c;他是ViewPager2中的一个接口 原理 要显示非默认屏幕滑动动画&#xff0c;请实现 ViewPager2.PageTransformer 接口并将其提供给 ViewPa…

jQuery(五)--自定义动画、动画

目录 一、自定义动画 1.1 animate() 1.2 animate()动画执行顺序 1.3 animate()动画回调函数和匀速运动 1.4 animate动画之stop()/delay() 二、动画 2.1 show()/hide()/toggle() 2.2 slideDown()/slideUp()/slideToggle() 2.3 fadeIn()/fadeOut()/fadeTo()/fadeToggle(…

Android ProgressBar 自定义动画

源码地址&#xff1a; https://download.csdn.net/download/dreams_deng/12236355 1. 自定义圆形动画 1.1 布局 <!-- indeterminateDrawable 旋转图片indeterminateDuration 旋转速度--><ProgressBarandroid:id"id/pb_welcome_loading"android:layout_…

Qt自定义动画移动路径

在使用Qt实现动画时&#xff0c;一般使用QPropertyAnimation来实现&#xff0c;一般我们实现控件的移动动画都是走直线&#xff0c;我们如何实现自己想要的移动路径呢&#xff0c;比如走圆弧。下面介绍通过QPropertyAnimation实现自定义动画移动路径&#xff0c;比如走圆曲线、…

Flutter开发之——动画-自定义动画

一 为什么要进行自定义动画 当系统提供的动画不满足业务需求时&#xff0c;就需要我们自己进行自定义动画通过自定义动画&#xff0c;可以提高自定义组件的能力 二 自定义动画过程 继承StatefulWidget &#xff0c;完成动画界面的绘制setState 中动画执行及状态监听并刷新UId…

JQuery自定义动画——animate()学习

JQuery自定义动画——animate()学习 可以使 用animate 方法创建和实现自定义动画&#xff0c;animate() 方法通过执行 CSS 属性集的自定义动画&#xff0c;满足更多复杂多变的要求。 该方法通过CSS样式将元素从一个状态改变为另一个状态。即通过CSS属性值逐渐改变的&#xff0…

搞定动画之 JQuery 中的自定义动画

古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志——苏轼 写在前面 所谓的自定义动画就是通过 jQuery 提供的方法来完成我们自己想要的动画效果 animate()方法 jQuery 提供了 animate() 方法完成自定义动画效果&#xff0c;该方法具有两种用法。 用…

animate.css 自定义动画

在使用animate.css 的时候 动画的高度超过了预期的高度 在这种情况下肯定是过不了测试的&#xff0c;怎么办的&#xff1f; <div class"fold-div animated " :class"{slideInDown:foldDivHeightShow}" </div>上边代码可以知道 用的是 slideInDown…

JQuery中的animate自定义动画

animate()方法用于创建自定义动画。 概述 .animate( properties [, duration ] [, easing ] [, complete ] ) properties 类型: PlainObject 一个CSS属性和值的对象,动画将根据这组对象移动。 duration (默认: 400) 类型: Number or String 一个字符串或者数字决定动画将运…

jQuery自定义动画

首先创建一个新的html&#xff0c;在body下面输入源代码&#xff1b;div标签代表的是颜色的面板&#xff0c;button标签代表的是按钮当我们输入好了源代码之后呢&#xff0c;那我们的源代码部分已经完成了&#xff0c;接下来剩下的就只有css样式和jQuery函数了 接下来我们先完成…

自定义动画

自定义动画非常简单&#xff0c;只需要实现它的applyTransformation的逻辑就可以了&#xff0c;不过通常情况下&#xff0c;还需要覆盖父类的initialize方法来实现一些初始化工作。applyTransformation方法有如下两个参数。 applyTransformation(float interpolatedTime, Trans…

自定义控件三部曲之动画篇(四)——ValueAnimator基本使用

前言&#xff1a;不要让别人的无知断送了你的梦想&#xff0c;永远坚信你所坚信的。 相关文章&#xff1a; 《Android自定义控件三部曲文章索引》&#xff1a;http://blog.csdn.net/harvic880925/article/details/50995268 一、概述 long long ago&#xff0c;我写过几篇有关…

[HTML/CSS]动画效果以及自定义动画效果

一&#xff0c;实现div或者文字的当鼠标浮于其上时的动画效果&#xff1a; 1&#xff0c;transition加在div中&#xff0c;实现动画效果的过渡效果&#xff0c;transition: all 3s;其中all表示所有样式都参与过渡&#xff0c;3s表示实现效果的时间&#xff1b;linear为使动画匀…

css如何让文字强制换行

我们在编写html时&#xff0c; 有时候&#xff0c;常常需要在移动端用到一些table的属性&#xff0c;来呈现一些数据。如果说我们的数据内不含连续的数字或字母时&#xff0c;显示是不会出错的。 可是如果我们要呈现的数据为数字或长字母信息时&#xff0c;常常会出现这样的情…

CSS文本强制换行

发生背景&#xff1a; 在没有空格的&#xff08;字母、数字&#xff0c;符号&#xff09;&#xff0c;超过容器宽度时就会把容器撑大&#xff0c;不换行。所以在这里需要对其设置强制换行的样式&#xff1b; 解决方案&#xff1a; /* word-wrap: break-word; */ /…

css强制换行和禁止换行

强制换行 word-break: break-all; /* 只对英文起作用&#xff0c;以字母作为换行依据。 */ word-wrap: break-word; /* 只对英文起作用&#xff0c;以单词作为换行依据。 */ white-space: pre-wrap; /* 只对中文起作用&#xff0c;强制换行。 */ 禁止换行 white-space:…

Css 强制英文自动换行以及word-wrap、word-break、white-space、overflow的用法

关于换行的几个知识点&#xff1a; 1、Css强制英文或数字自动换行 2、让中文按关键词或标签换行 3、Css强制中文不自动换行 4、Css强制中文不自动换行并自动隐藏&#xff1b; 5、Css中英文或数字的超出部分自动省略号…&#xff1b; 6、Css中word-wrap、word-break、white-spa…

功能测试的用例测试方法

一、等价类划分法&#xff1a; 即把所有可能输入的数据划分为若干个区域&#xff0c;然后从每个区域中取少数有嗲表行的数据进行测试。 例1&#xff1a;某网页的年龄输入框要求输入20~99的整数。&#xff08;说明&#xff1a;当输入的数据复合取值范围要求时提示&#xff1a;…

计算机性能检查方法,测试电脑性能的方法步骤详解

想知道自己电脑的运行性能吗?下面就让学习啦小编教大家如何测试电脑的性能吧。 测试电脑性能的方法 1.使用系统功能进行评测电脑的运行性能 这种方法就是通过windows自带的评测功能进行测试。 打开资源管理器&#xff0c;右键点击“属性”&#xff0c;进入到相应的窗口中来! 如…

性能测试七种常用方法,以及四大应用领域

文章目录 什么是性能测试性能指标测试模型测试种要有监控有预定条件性能测试中要有场景性能测试中有分析调优性能测试结果报告 常用的七种性能测试方法后端性能测试前端性能测试代码级性能测试压力测试配置测试并发测试可靠性测试 性能测试的四大应用领域能力验证能力规划性能调…