本文使用 UE4.26 版本,ActionRPG 教程为例,通过代码实现通过动画序列自动生成蒙太奇的功能。
包括:

  1. 批量通过动画生成对应蒙太奇(UE4 自带,但是需要改)
  2. 通过多个动画拼成一个蒙太奇,并设置对应的 Sections

一、功能背景

1.1 需求和场景

  1. 很多动画蒙太奇(AM)是直接通过动画序列(A),在 Content 目录下直接右键新建蒙太奇生成的,不需要有什么修改,理论应该可以批量生成
  2. 有些蒙太奇是通过多个 A 拼接而成,其中 Section 的位置以及名字都是固定的(位置和动画对齐,名字固定)

  在这种情况下,程序直接批量生成,会大幅提升效率,并提升质量(只要保证动画没错,就不会出现策划配错了的情况),而且策划也懒得配。。

1.2 所需背景知识

  只需要很基础的只是,就是蒙太奇上的 Section 和 Slot,以及 Segment 具体是什么,以及是干嘛用的。

UCLASS(config=Engine, hidecategories=(UObject, Length), MinimalAPI, BlueprintType)
class UAnimMontage : public UAnimCompositeBase
{GENERATED_UCLASS_BODY()// composite section. UPROPERTY()TArray<FCompositeSection> CompositeSections;// slot data, each slot contains anim trackUPROPERTY()TArray<struct FSlotAnimationTrack> SlotAnimTracks;
}

  上边是蒙太奇类中,这篇文章中关心的两个成员: CompositeSections(简称 Sections)以及 SlotAnimTracks(简称 Slot,主要关心里边的 Segments)。

1.2.1 CompositeSections

  下图中三个红框就是三个 Section,这个蒙太奇的 CompositeSections 大小就是 3。

  Section 用来把动画分成多段。可以循环,可以跳过等等操作,如下,是技能中,直接跳到蒙太奇某一段的函数:

void UGameplayAbility::MontageJumpToSection(FName SectionName)
{check(CurrentActorInfo);UAbilitySystemComponent* const AbilitySystemComponent = GetAbilitySystemComponentFromActorInfo_Checked();if (AbilitySystemComponent->IsAnimatingAbility(this)){AbilitySystemComponent->CurrentMontageJumpToSection(SectionName);}
}

1.2.2 Slot 和 Segment

  下图中,左边这个 Default.Default 是一个 Slot,即这个蒙太奇 SlotAnimTracks 大小是 1(一般就一个 Slot)。

USTRUCT()
struct FSlotAnimationTrack
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, Category=Slot)FName SlotName;UPROPERTY(EditAnywhere, Category=Slot)FAnimTrack AnimTrack;
};

  一个 Slot 中有一个 AnimTrack

USTRUCT()
struct FAnimTrack
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, Category=AnimTrack, EditFixedSize)TArray<FAnimSegment>  AnimSegments;
}

  每个 AnimTrack 中有 AnimSegments,每个 Segment 中是一段动画,包括动画序列,开始时间,结束时间,在蒙太奇中的开始时间等。

/** this is anim segment that defines what animation and how **/
USTRUCT()
struct FAnimSegment
{GENERATED_USTRUCT_BODY()/** Anim Reference to play - only allow AnimSequence or AnimComposite **/UPROPERTY(EditAnywhere, Category=AnimSegment)UAnimSequenceBase* AnimReference;/** Start Pos within this AnimCompositeBase */UPROPERTY(VisibleAnywhere, Category=AnimSegment)float   StartPos;/** Time to start playing AnimSequence at. */UPROPERTY(EditAnywhere, Category=AnimSegment)float   AnimStartTime;/** Time to end playing the AnimSequence at. */UPROPERTY(EditAnywhere, Category=AnimSegment)float    AnimEndTime;/** Playback speed of this animation. If you'd like to reverse, set -1*/UPROPERTY(EditAnywhere, Category=AnimSegment)float    AnimPlayRate;UPROPERTY(EditAnywhere, Category=AnimSegment)int32        LoopingCount;
}

   需要注意的是:

  1. section 的位置不一定需要和每一段动画开头对上,可以在任意位置,不过拖动 Section 靠近动画开头,会有吸力,松手就自动对齐
  2. Segment 的 StartPosAnimStartTime 很容易混淆:
  • StartPos - 这一段动画,在整个蒙太奇的什么时间开始
  • AnimStartTime - 这个 Segment,是从对应的动画的什么时候开始,一般是 0,即从头开始
  • AnimEndTime - 同上,这个 Segment 播放到动画的什么时候结束,一般是动画长度,即完整播完
  • AnimPlayRate - 这个 Segment 中动画播放速度,默认1,例如,如果是 2,则这段动画只需要一半时间就两倍速播完
  • LoopingCount - 这段动画的循环次数,默认 1,如果是0,则这段动画就没了,不是一直循环的意思(一致循环通过 Section 实现)

二、实现效果

三、实现方法

3.1 参考方法

3.1.1 右键生成蒙太奇效果

  参考方法就是在 Content 中右键一个动画序列,然后选择 Create -> Create AnimMontage,的功能,如下图所示:

  这样生成的蒙太奇包括一个 Section,叫作 Default,和一个 Segment,就是选择的动画。

  注意:

  1. 这个右键操作生成的蒙太奇,名称默认为 xx_Montage,xx 是动画资源的名称(如果这个名字的蒙太奇已经有了,则会是 xx_Montage1,以此类推),所以不会出现把原有文件覆盖的问题;
  2. 这个操作可以批量生成,选十个动画,然后右键生成蒙太奇,就是会生成这十个动画对应的十个蒙太奇,并不会十个动画拼接成一个蒙太奇;

3.1.2 右键生成蒙太奇代码

  这种有按钮,有界面的功能,一般直接搜索对应的 Tips 文字就能找到功能,即 Creates an AnimMontage using the selected anim sequence

MenuBuilder.AddMenuEntry(LOCTEXT("AnimSequence_NewAnimMontage", "Create AnimMontage"),LOCTEXT("AnimSequence_NewAnimMontageTooltip", "Creates an AnimMontage using the selected anim sequence."),FSlateIcon(FEditorStyle::GetStyleSetName(), "ClassIcon.AnimMontage"),FUIAction(FExecuteAction::CreateSP(this, &FAssetTypeActions_AnimSequence::ExecuteNewAnimMontage, Sequences),FCanExecuteAction()));

  即 ExecuteNewAnimMontage 函数,里边调用的就是 FAssetTypeActions_AnimSequence::CreateAnimationAssets

/** Creates animation assets of the supplied class */
void CreateAnimationAssets(const TArray<TWeakObjectPtr<UAnimSequence>>& AnimSequences,  /* 所选中的动画序列资源,可以是多个 */TSubclassOf<UAnimationAsset> AssetClass, /* 要生成的动画资源类型, 即 - UAnimMontage::StaticClass() */UFactory* AssetFactory,                  /* 蒙太奇生成工厂 - NewObject<UAnimMontageFactory>() */const FString& InSuffix,                 /* 生成的资源名称后缀, 默认 - TEXT("_Montage"); */FOnConfigureFactory OnConfigureFactory) const;

  这个方法中根据 AnimSequences 的数量分了两部分,一种是只有一个动画资源的,直接生成对应的蒙太奇;一种是有多个动画资源的,生成多个蒙太奇。实际只需要看一个动画的部分:

auto AnimSequence = AnimSequences[0].Get();if ( AnimSequence )
{// Determine an appropriate name for inline-renameFString Name;FString PackageName;CreateUniqueAssetName(AnimSequence->GetOutermost()->GetName(), InSuffix, PackageName, Name);if (OnConfigureFactory.IsBound()){if (OnConfigureFactory.Execute(AssetFactory, AnimSequence)){FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");ContentBrowserModule.Get().CreateNewAsset(Name, FPackageName::GetLongPackagePath(PackageName), AssetClass, AssetFactory);}}
}

  其中 CreateUniqueAssetName 是判断生成的资源叫什么名字,默认 xx_Montage,如果有冲突,则 xx_Montage1,实际生成,就是 CreateNewAsset,上边的 OnConfigureFactory 的用处就是绑定一下动画是哪个。

3.2 实际方法

3.2.1 批量通过动画生成对应蒙太奇

  其实 UE 自带的就是这个功能,不需要怎么改,但是由于名字会自动变,如果想生成特定名字,且覆盖原有的话,需要改引擎。

UObject* UAssetToolsImpl::CreateAsset(const FString& AssetName, const FString& PackagePath, UClass* AssetClass, UFactory* Factory, FName CallingContext)
{const FString PackageName = UPackageTools::SanitizePackageName(PackagePath + TEXT("/") + AssetName);// Make sure we can create the asset without conflictsif (!CanCreateAsset(AssetName, PackageName, LOCTEXT("CreateANewObject", "Create a new object")) ){return nullptr;}// 生成资源 blablareturn NewObj;
}

  最终生成资源,调到的就是最后这个函数,但是在生成资源之前,会进行是不是 Exist 的检查,如果有,则会弹出消息框,需要点。

UObject* ExistingObject = StaticFindObject( UObject::StaticClass(), Pkg, *AssetName );
if( ExistingObject != nullptr )
{// Object already exists in either the specified package or another package.  Check to see if the user wants// to replace the object.bool bWantReplace =EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo,EAppReturnType::No,FText::Format(NSLOCTEXT("UnrealEd", "ReplaceExistingObjectInPackage_F", "An object [{0}] of class [{1}] already exists in file [{2}].  Do you want to replace the existing object?  If you click 'Yes', the existing object will be deleted.  Otherwise, click 'No' and choose a unique name for your new object." ),FText::FromString(AssetName),FText::FromString(ExistingObject->GetClass()->GetName()), FText::FromString(PackageName) ) );
}

  消息框自定义可以看这篇。
  如果有二十个冲突的蒙太奇,则需要点二十下,如果不想点,就要改引擎,CreateAsset 加个参数 - 要不要考虑冲突,然后直接不检查了。

3.2.2 多个动画拼成一个蒙太奇

  多个动画拼接成一个蒙太奇(如 1.2.2 中所示),可以先用一个动画,按照 3.2.1 的方法生成一个蒙太奇,然后调整对应的 CompositeSections以及 SlotAnimTracks 即可。
  注意:创建了 Section 之后,需要设置 NextSectionName,不然只会播一个 Section 的动画;如果希望其中某一段循环,让它的下一段是自己即可:

CompositeSections[3].NextSectionName = CompositeSections[3].SectionName;

四、参考资料

  1. Animation Montage Overview(官方 docs)
  2. Introduction to AnimMontage(官方 blog)

【UE4】通过动画序列自动生成蒙太奇(In Code)相关推荐

  1. 西门子界面官方精美触摸屏+WINCC程序模板 西门子官方触摸屏程序模板,炫酷的扁平式动画效果,脚本动画,自动生成二维码,可仿真,堪比智能手机,有精简,精致,wincc,无线面板等包含了所有西门子人机界

    西门子界面官方精美触摸屏+WINCC程序模板 西门子官方触摸屏程序模板,炫酷的扁平式动画效果,脚本动画,自动生成二维码,可仿真,堪比智能手机,有精简,精致,wincc,无线面板等包含了所有西门子人机界 ...

  2. dm数据库无法用序列自动生成主键,无法解析的成员访问表达式【SEQ_STU_CON_NEXTVAL】

    报错信息: 无法解析的成员访问表达式[SEQ_STU_CON_NEXTVAL] select SEQ_STU_CON_NEXTVAL 这种错的解决方案,在dm数据库中创建一个序列叫SEQ_STU_CO ...

  3. oracle创建表,序列,触发器,自动生成唯一主键

    数据库oracle和mysql插入数据的区别? mysql数据库主键字段是increament,则插入数据不需要插入主键字段.数据库会自动生成主键 oracle数据库主键字段必须创建序列,则插入数据必 ...

  4. UE4(Unreal Engine4)在蒙太奇动画中添加音频轨道通知

    UE4系列文章目录 文章目录 UE4系列文章目录 前言 一.遇到的问题 二.操作步骤 前言 UE4(Unreal Engine4)在蒙太奇动画中添加音频轨道通知,我们想在某一帧动画中添加声音.比如我们 ...

  5. 语音识别插件_2D动画唇动合成,根据语音自动生成动画人物口型

    蕾师师 发自 凹非寺 量子位 报道 | 公众号 QbitAI 只需要输入一段语音,代码会自动生成与之相对的动画唇形. 还是毫无违和感的那种. 这是一个在GitHub上拥有501星的开源项目,叫做Rhu ...

  6. Mockplus Cloud自动生成规格,Mockplus Cloud交互式动画原型

    Mockplus Cloud自动生成规格,Mockplus Cloud交互式动画原型 Mockplus Cloud 帮助您连接整个产品设计工作流程,让设计协作更轻松.它可以让您从 Sketch.Ado ...

  7. [Unity编辑器] 根据图片自动生成动画

    根据自己的情况 仿照 雨松MOMO 写了一个自动生成动画的脚本 原地址 http://www.xuanyusong.com/archives/3243 代码: using UnityEngine; u ...

  8. adobe xd导出html,Adobe XD2018年10月更新,自动生成动画、导出到 After Effects等功能...

    Adobe XD 是一款超前且免费的用户体验设计工具,可以轻松完成网站.移动应用程序.语音交互.触摸屏等内容的设计和原型创建,目前保持每月更新一次的节奏,10月的今天,在Adobe MAX 2018到 ...

  9. 2D动画唇动合成,根据语音自动生成动画人物口型

    蕾师师 发自 凹非寺 量子位 报道 | 公众号 QbitAI 只需要输入一段语音,代码会自动生成与之相对的动画唇形. 还是毫无违和感的那种. 这是一个在GitHub上拥有501星的开源项目,叫做Rhu ...

最新文章

  1. List嵌套List数据,全部List数组一起更新问题
  2. Raspberry Zero 上实现平滑视频图传
  3. 函数和闭包之头等函数
  4. Spring Boot spring mvc 拦截器
  5. 关于redis的文章
  6. jQuery 插件 Validation表单验证 使用步骤(详细的)
  7. CSS深入理解学习笔记之vertical-align
  8. Linux 命令(94)—— env 命令
  9. Jquery事件委托之Safari
  10. python32位 最大内存_64位windows上的Python 32位内存限制
  11. 在OSPF网络中,如何判断LSA的新旧?
  12. nginx做负载均衡+keepalived(做主备)
  13. CONVERT TEXT(转换为可排序格式)
  14. 高质量Python书籍推荐丨Python学习手册(第5版)
  15. LU分解算法(串行、并行)
  16. 企业微信员工离职后,还能看聊天记录吗?
  17. 推荐21个高质量图片网站,免费免版权,值得收藏
  18. python bytes
  19. cookie用法--抽屉网的自动登录(cookie是通过代码自动获取的)
  20. 微信扫付款后,付错款,不是好友也能联系到收款方

热门文章

  1. SQL Server数据库插入数据中文显示乱码问题
  2. 极客时间_软件设计之美 笔记
  3. K均值与DBSCAN聚类效果
  4. 评估方法(交叉验证法、自助法、留出法)
  5. PHP-Swoole+tp3+websocket+redis,利用接口制作客服实时对话聊天服务器
  6. java控制台存钱方法_JAVA实现账户取款和存款操作
  7. 平面四连杆运动方程分析with matlab
  8. goldendict使用 添加 .blg 添加字典
  9. C#编程学习49:将数据写入到excel中
  10. 第1期-软件测试-简历-正确编写测试简历的姿势