[UE4]AI中使用Tick()函数的性能问题

本文探讨了在Unreal Engine 4 (UE4)中使用Tick函数控制AI的传统做法及其存在的性能问题,并介绍了现代AI设计中采用事件驱动和行为树的方法来提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Tick()函数一般是debug时用的,正规的逻辑中,如果要用Tick函数,可以考虑用UE4提供的事件代理(Event Delegate:http://aigo.iteye.com/blog/2301010)。

 

参考:
Using Tick() within AI?

https://answers.unrealengine.com/questions/62519/using-tick-within-ai.html

 

Using Tick for controlling AI has a (very) long tradition, so it's a good start. Nowadays we don't do that since every tick counts (as if it was not the case more years back! ;)). The main problem with tick is that most of the time your AI won't have anything new to do every tick, so most of that Tick function calls will be wasted performance.

The right way to do AI is to have it event driven, where AI responds to events in the world (like being shot) and case of no events it's just performing some kind of scripted behavior (scripted in a sense there's a piece of code producing a sequence of action that AI follows).

UE4's way of controlling AI is by Behavior Trees. And don't be scared by the "Experimental" label - all that's experimental in our BTs are tools, and only because they just need the Epic polish to reach the right quality bar. I strongly encourage everyone to use it! :D

Cheers,

--mieszko

 

 

<think>我们正在处理用户关于UnrealEngine中Tick函数AIMoveTo用法或问题的查询。首先,我们需要明确这两个概念在UE中的角色。1.**Tick函数**:在UE中,Tick是Actor或Component每帧调用的函数,用于执行每帧需要更新的逻辑。它类似于游戏循环中的更新部分。2.**AIMoveTo**:这是AI模块中的一个函数,用于让AI角色移动到指定位置。它通常与行为树(BehaviorTree)和AI控制器(AIController)一起使用。用户可能关心如何在Tick中正确使用AIMoveTo,或者在使用过程中可能遇到的问题(如性能问题、移动不准确等)。根据引用内容,我们注意到引用[1]提到:“FixedAInotgettingnotifiedaboutexternally-causednavigationpathupdates,likeforexamplewhenmovegoalactorchangeslocation”。这暗示了在外部原因导致导航路径更新(例如目标位置改变)时,AI可能无法及时得到通知的问题已被修复。因此,在使用AIMoveTo时,如果目标位置动态变化,需要确保AI能够更新路径。###使用建议:-通常,我们不建议在Tick函数中频繁调用AIMoveTo,因为这样会导致每帧都请求新的移动,可能造成性能问题(导航路径计算开销较大)和逻辑混乱。-更好的做法是在需要的时候调用(例如,当目标位置改变时),并且使用事件驱动的方式(例如,通过事件触发移动,或者使用行为树的任务节点)。###常见问题及解决方案:1.**性能问题**:在Tick中调用AIMoveTo会导致每帧都计算路径,造成性能负担。解决方案:避免在Tick中调用,改为在目标位置变化时调用,或者设置一个冷却时间。2.**移动不更新**:如果目标位置在移动过程中改变,AI可能不会重新计算路径(如引用[1]所述,该问题已被修复,但可能仍需注意)。解决方案:在目标位置变化时,显式地调用AIMoveTo来更新移动。3.**移动中断**:当新的AIMoveTo调用时,会中断当前的移动。因此,在Tick中调用会导致移动不断重新开始,看起来像是在“抖动”。解决方案:只在必要的时候调用。###示例代码:假设我们有一个AI角色,当玩家靠近时,AI会移动到玩家位置。我们不应该在Tick中每帧调用AIMoveTo,而是应该检测玩家位置变化,当变化超过一定阈值时再调用。以下是一个示例(在AIController类中):```cppvoidAAIController::Tick(floatDeltaTime){Super::Tick(DeltaTime);//不推荐在Tick中直接调用AIMoveTo//推荐做法:通过检查目标位置变化来决定是否重新移动if(TargetActor){FVectorCurrentTargetLocation=TargetActor->GetActorLocation();if(FVector::DistSquared(CurrentTargetLocation,LastTargetLocation)>FMath::Square(UpdateThreshold)){//目标位置变化超过阈值,重新移动MoveToLocation(CurrentTargetLocation);LastTargetLocation=CurrentTargetLocation;}}}```但是,更好的做法是使用事件机制,例如在目标位置变化时触发一个事件,然后在事件处理函数中调用AIMoveTo。###引用说明:引用[1]提到的问题修复,确保了当移动目标的位置由外部原因(比如另一个系统)改变时,AI能够被通知并更新路径。因此,在较新的引擎版本中,如果目标位置改变,我们可以依赖引擎自动更新路径(但具体还要看实现),但我们仍然要注意避免过于频繁的调用。###总结:-避免在Tick中每帧调用AIMoveTo,改为在需要更新路径时调用(如目标位置变化)。-注意引擎版本,引用[1]中的修复可能已经解决了目标位置变化时的路径更新问题,但频繁调用仍会导致性能问题。-考虑使用行为树来管理AI移动,行为树中的MoveTo任务可以配置为只在目标位置变化时重新规划路径。§§相关问题§§1.如何在UnrealEngine中优化AI移动性能?2.UnrealEngine中AIMoveTo的常见问题及解决方法有哪些?3.如何让AI在移动过程中动态调整路径?</think>### Unreal Engine中Tick函数AIMoveTo的用法解析 #### 1. **Tick函数基础** TickUE中Actor/Component的核心更新机制,通过`Tick(float DeltaTime)`函数实现逐帧逻辑。关键注意事项: - **启用条件**:需在构造函数中设置`PrimaryActorTick.bCanEverTick = true`(Actor)或`bWantsInitializeComponent = true`(Component) - **频率控制**:使用`SetActorTickInterval()`调整执行间隔避免性能开销[^1] - **性能优化**:复杂计算应避免在Tick中执行,可改用定时器(Timer)或事件驱动 #### 2. **AIMoveTo的核心用法** `AIMoveTo`是`AIController`的导航方法,用于路径寻找: ```cpp // 基础调用示例 AIController->MoveToLocation(TargetLocation, AcceptanceRadius); ``` **关键参数**: - `AcceptanceRadius`:到达判定距离(单位:厘米) - `bStopOnOverlap`:是否接触即停止 - `bUsePathfinding`:是否使用导航网格 #### 3. **TickAIMoveTo的协同** 典型应用场景:在Tick中动态更新移动目标 ```cpp void AMyAI::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (bNeedUpdateTarget) { FVector NewTarget = CalculateDynamicPosition(); AIController->MoveToLocation(NewTarget); bNeedUpdateTarget = false; // 避免每帧调用 } } ``` **最佳实践**: 1. **避免每帧调用**:仅在目标变化时触发`AIMoveTo` 2. **路径检查**:调用前用`NavigationSystem->ProjectPointToNavigation()`验证可达性 3. **异步处理**:复杂目标计算改用`AsyncTask`防止卡顿 #### 4. **常见问题解决方案** | 问题现象 | 原因分析 | 解决方案 | |---------|---------|---------| | AI原地抖动 | 每帧重置移动目标 | 添加移动状态机,仅当目标变化>阈值时更新 | | 路径失效 | 动态障碍物遮挡 | 启用`NavModifierComponent`并监听`OnNavDataChanged`事件[^1] | | 性能骤降 | Tick中频繁寻路 | 使用`AIAsyncTask`异步计算路径 | | 移动中断 | Tick覆盖移动指令 | 通过`GetMoveStatus()`检查当前移动状态 | #### 5. **高级优化技巧** - **导航缓存**:对固定路径使用`UNavigationPath`预计算 - **分层更新**:关键AITick,次要AI用`FTickFunction`分级调度 - **移动预测**:结合`UCharacterMovementComponent`的速度向量进行路径插值 - **调试工具**:控制台命令`ShowDebug Navigation`可视化寻路过程 > ⚠️ **重要提醒**:UE 5.1+ 优化了导航更新机制,当外部因素改变目标位置时(如移动平台),引擎会自动通知AI系统更新路径[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值