当前位置: 首页 > news >正文

UE5 为啥原生的NotifyState写逻辑会有问题

UE5 为啥原生的NotifyState写逻辑会有问题

虚幻的UAnimNotifyState,也就是Montage中配置的通知条存在明显的问题,请勿用来写逻辑,做表现是可以的。

UE5.3 相关源码:

void UAnimInstance::TriggerAnimNotifies(float DeltaSeconds)
{SCOPE_CYCLE_COUNTER(STAT_AnimTriggerAnimNotifies);USkeletalMeshComponent* SkelMeshComp = GetSkelMeshComponent();// Array that will replace the 'ActiveAnimNotifyState' at the end of this function.TArray<FAnimNotifyEvent> NewActiveAnimNotifyState;NewActiveAnimNotifyState.Reserve(NotifyQueue.AnimNotifies.Num());TArray<FAnimNotifyEventReference> NewActiveAnimNotifyEventReference;NewActiveAnimNotifyEventReference.Reserve(NotifyQueue.AnimNotifies.Num());// AnimNotifyState freshly added that need their 'NotifyBegin' event called.TArray<const FAnimNotifyEvent *> NotifyStateBeginEvent;TArray<const FAnimNotifyEventReference *> NotifyStateBeginEventReference;for (int32 Index=0; Index<NotifyQueue.AnimNotifies.Num(); Index++){if(const FAnimNotifyEvent* AnimNotifyEvent = NotifyQueue.AnimNotifies[Index].GetNotify()){// AnimNotifyStateif (AnimNotifyEvent->NotifyStateClass){int32 ExistingItemIndex = INDEX_NONE;if (ActiveAnimNotifyState.Find(*AnimNotifyEvent, ExistingItemIndex)){check(ActiveAnimNotifyState.Num() == ActiveAnimNotifyEventReference.Num());ActiveAnimNotifyState.RemoveAtSwap(ExistingItemIndex, 1, false); ActiveAnimNotifyEventReference.RemoveAtSwap(ExistingItemIndex, 1, false);}else{NotifyStateBeginEvent.Add(AnimNotifyEvent);NotifyStateBeginEventReference.Add(&NotifyQueue.AnimNotifies[Index]);}NewActiveAnimNotifyState.Add(*AnimNotifyEvent);FAnimNotifyEventReference& EventRef = NewActiveAnimNotifyEventReference.Add_GetRef(NotifyQueue.AnimNotifies[Index]);EventRef.SetNotify(&NewActiveAnimNotifyState.Top());continue;}// Trigger non 'state' AnimNotifiesTriggerSingleAnimNotify(NotifyQueue.AnimNotifies[Index]);}}// Send end notification to AnimNotifyState not active anymore.for (int32 Index = 0; Index < ActiveAnimNotifyState.Num(); ++Index){const FAnimNotifyEvent& AnimNotifyEvent = ActiveAnimNotifyState[Index];const FAnimNotifyEventReference& EventReference = ActiveAnimNotifyEventReference[Index];if (AnimNotifyEvent.NotifyStateClass && ShouldTriggerAnimNotifyState(AnimNotifyEvent.NotifyStateClass)){
#if WITH_EDITOR// Prevent firing notifies in animation editors if requested if(!SkelMeshComp->IsA<UDebugSkelMeshComponent>() || AnimNotifyEvent.NotifyStateClass->ShouldFireInEditor())
#endif{TRACE_ANIM_NOTIFY(this, AnimNotifyEvent, End);AnimNotifyEvent.NotifyStateClass->NotifyEnd(SkelMeshComp, Cast<UAnimSequenceBase>(AnimNotifyEvent.NotifyStateClass->GetOuter()), EventReference);}}// The NotifyEnd callback above may have triggered actor destruction and the tear down// of this instance via UninitializeAnimation which empties ActiveAnimNotifyState.// If that happened, we should stop iterating the ActiveAnimNotifyState arrayif (ActiveAnimNotifyState.IsValidIndex(Index) == false){ensureMsgf(false, TEXT("UAnimInstance::ActiveAnimNotifyState has been invalidated by NotifyEnd. AnimInstance: %s, Owning Component: %s, Owning Actor: %s "), *GetNameSafe(this), *GetNameSafe(GetOwningComponent()), *GetNameSafe(GetOwningActor()));return;}}check(NotifyStateBeginEventReference.Num() == NotifyStateBeginEvent.Num());for (int32 Index = 0; Index < NotifyStateBeginEvent.Num(); Index++){const FAnimNotifyEvent* AnimNotifyEvent = NotifyStateBeginEvent[Index];const FAnimNotifyEventReference * AnimNotifyEventReference = NotifyStateBeginEventReference[Index];if (ShouldTriggerAnimNotifyState(AnimNotifyEvent->NotifyStateClass)){
#if WITH_EDITOR// Prevent firing notifies in animation editors if requested if(!SkelMeshComp->IsA<UDebugSkelMeshComponent>() || AnimNotifyEvent->NotifyStateClass->ShouldFireInEditor())
#endif{TRACE_ANIM_NOTIFY(this, *AnimNotifyEvent, Begin);AnimNotifyEvent->NotifyStateClass->NotifyBegin(SkelMeshComp, Cast<UAnimSequenceBase>(AnimNotifyEvent->NotifyStateClass->GetOuter()), AnimNotifyEvent->GetDuration(), *AnimNotifyEventReference);}}}// Switch our arrays.ActiveAnimNotifyState = MoveTemp(NewActiveAnimNotifyState);ActiveAnimNotifyEventReference = MoveTemp(NewActiveAnimNotifyEventReference);// Tick currently active AnimNotifyStatefor (int32 Index = 0; Index < ActiveAnimNotifyState.Num(); Index++){const FAnimNotifyEvent& AnimNotifyEvent = ActiveAnimNotifyState[Index];const FAnimNotifyEventReference& EventReference = ActiveAnimNotifyEventReference[Index];if (ShouldTriggerAnimNotifyState(AnimNotifyEvent.NotifyStateClass)){
#if WITH_EDITOR// Prevent firing notifies in animation editors if requested if(!SkelMeshComp->IsA<UDebugSkelMeshComponent>() || AnimNotifyEvent.NotifyStateClass->ShouldFireInEditor())
#endif{TRACE_ANIM_NOTIFY(this, AnimNotifyEvent, Tick);AnimNotifyEvent.NotifyStateClass->NotifyTick(SkelMeshComp, Cast<UAnimSequenceBase>(AnimNotifyEvent.NotifyStateClass->GetOuter()), DeltaSeconds, EventReference);}}}
}

问题一:同帧下的Begin 与End,它是按For循环执行的,没有按照时间顺序执行。如下图的NotifyStateA与NotifyStateB,他们在第N帧的时候,A的End会要比B的Start先执行,但是在时间的顺序上,B的Begin时间是早于A的End的,如果依赖时间顺序去执行,某些代码逻辑时候,当卡的时候,逻辑必有问题。
在这里插入图片描述
问题二:它没有上下执行顺序的问题,并不是同一时间下上面的先执行。
问题三:同一帧里面有NotifyState的Start 与 End,那么End会在下一帧执行,而不是同帧下执行
在这里插入图片描述

http://www.dtcms.com/a/362355.html

相关文章:

  • Java异常处理详解:掌握try-catch-finally与try-with-resources,避开空指针等踩坑点
  • 20250901的学习笔记
  • 全栈智算系列直播回顾 | 智算中心对网络的需求与应对策略(下)
  • 【LeetCode】3670. 没有公共位的整数最大乘积 (SOSDP)
  • 笔记:人工神经网络
  • Vue基础知识-Vue中:class与:style动态绑定样式
  • DiffusionGPT-LLM驱动的文本生成图像系统
  • OpenStack网络类型解析
  • Markdown 语法全面指南
  • EXPLAIN 和 EXPLAIN ANALYZE
  • 【AI报表】JimuReport 积木报表 v2.1.3 版本发布,免费可视化报表和大屏
  • Python 爬虫案例:爬取豆瓣电影 Top250 数据
  • 【开题答辩全过程】以 基于SSM的高校疫情防控管理系统为例,包含答辩的问题和答案
  • docker中的命令(六)
  • 轻量实现 OCPP 1.6 JSON 协议(欧洲版)的充电桩调试平台
  • AI使用指南:9月开学季,自动生成教学PPT
  • C++ 用于运行时类型识别的typeinfo库使用指南
  • 飞致云开源社区月度动态报告(2025年8月)
  • 苍穹外卖项目实战(日记十三)-记录实战教程及问题的解决方法-(day3-5) 修改菜品功能实现
  • C# FlaUI win 自动化框架,介绍
  • 用只能以关键字指定和只能按位置传入的参数来设计清晰的接口(Effective Python 第25条)
  • 利用 DrissionPage 精准获取淘宝商品描述:Python 爬虫实战指南
  • shell之扩展
  • 奇瑞QQ的后轮制动器设计cad+三维图+设计说明书
  • 【Java】谈谈IdentityHashMap
  • 前阿里专家揭秘:你对中国十大GEO专家的认知,99%都是错的
  • 苹果ipa应用安装包ios系统闪退问题
  • 携程旅行网景区,评论数据爬虫项目数据库保存附源码
  • 需求工程——你真的懂吗
  • C 基础(1) - 初识C语言