Unreal 寻路网格
文章目錄
- Agent 的挑選
- Nav Data是什么
- NavLinkProxy是什么
- 尋路網(wǎng)格算法
- Build Path 流程
- 虛幻Recast dtNavMesh Build流程
- 修改尋路網(wǎng)格
- 動態(tài)修改尋路
- DynamicModifiersOnly
- 優(yōu)化動態(tài)修改尋路
- 大世界下尋路網(wǎng)格的使用
- 1 老辦法
- 2 只在周圍生成
- 3 world-partitioned做法
- 操作
- 原理
Agent 的挑選
在項(xiàng)目設(shè)置內(nèi),Navigation System 內(nèi)可以配置一些Agents
在尋路過程中,使用移動組件內(nèi)的配置去匹配所有Agents
具體的函數(shù)如下:
const ANavigationData* UNavigationSystemV1::GetNavDataForProps(const FNavAgentProperties& AgentProperties) const匹配的規(guī)則:
-
首先判斷 Preferred Nav Data 是否匹配:
return (PreferredNavData == Other.PreferredNavData || PreferredNavData.IsNull() || Other.PreferredNavData.IsNull()); -
然后用 AgentRadius 和 AgentHeight 進(jìn)行匹配(默認(rèn)-1,表示使用膠囊體),挑出最匹配的那個(gè)
- 單項(xiàng)更優(yōu)判斷:較大的優(yōu)先(Agent 比目標(biāo)大,至少不會出現(xiàn)卡住的情況),都比目標(biāo)大或者小的情況下,較接近的優(yōu)先
- 若不符合兩項(xiàng)都較優(yōu)或相同,且之前的Agent不合法(兩項(xiàng)有一項(xiàng)是小于目標(biāo)的),則先使用半徑判斷,若相同再用高度判斷,只有有一項(xiàng)是較優(yōu)則替換
- 所以,Agent的設(shè)置和實(shí)際的相同或者大一些
- 注意這里兩項(xiàng)相同的情況也會替換,而List本身是項(xiàng)目設(shè)置內(nèi)的逆序,所以默認(rèn)的Agent排在上面
Nav Data是什么
在 Build Path 時(shí),World 內(nèi)會為每一個(gè) Agent 生成一份 NavigationData,用于這種類型角色的尋路。具體流程是:A 在尋路時(shí),根據(jù)(PreferredNavData、AgentRadius、AgentHeight)找到最符合的 Agent,然后使用該 Agent 對應(yīng)的 NavigationData,進(jìn)行路徑搜索,最后找出 N 個(gè)點(diǎn),就是尋找到的路徑,然后 AI 就按照這條路徑操縱移動組件進(jìn)行移動(移動流程參考UE4:AI‘s MoveTo——代碼分析)
而每個(gè) Agent 有自己的 Nav Data Class,也就是說同樣體型不同 Nav Data Class 的情況下需要兩個(gè) Agent,以飛行為例,我們需要兩個(gè) Agent,一個(gè)Walk,一個(gè)Fly,當(dāng)需要進(jìn)行飛行尋路時(shí),就需要找到 Fly 這個(gè) Agent。而 Fly Agent 生成的 NavigationData,就是用于飛行尋路的基礎(chǔ)數(shù)據(jù)。
NavLinkProxy是什么
有一些游戲機(jī)制(例如傳送門),使得我們的路徑?jīng)]法使用單純自動生成的尋路網(wǎng)格,需要增加一些處理。這種情形下我們會用到NavLinkProxy,將兩個(gè)點(diǎn)之間聯(lián)通(可選單向),我們的尋路就會將這兩個(gè)點(diǎn)聯(lián)通。
當(dāng)AI到達(dá)點(diǎn)A時(shí),會觸發(fā)NavLinkProxy的Receive Smart Link Reached,這里我們可以自定義AI所需要觸發(fā)的函數(shù),例如響應(yīng)傳說。
尋路網(wǎng)格算法
https://zhuanlan.zhihu.com/p/359376662
https://zhuanlan.zhihu.com/p/74537236
Build Path 流程
在Build - Build Path,進(jìn)入到UNavigationSystemV1::Build()
UNavigationSystemV1::Build()
- void UNavigationSystemV1::SpawnMissingNavigationData()
- void UNavigationSystemV1::RebuildAll(bool bIsLoadTime)
- FNavDataGenerator::RebuildAll
就是對每個(gè)NavData,運(yùn)行NavDataGenerator的RebuildAll函數(shù)
虛幻Recast dtNavMesh Build流程
https://docs.unrealengine.com/4.27/en-US/API/Runtime/Navmesh/Detour/dtNavMesh/
修改尋路網(wǎng)格
將 DirtyArea 塞入 DirtyAreasController 的 TArray<FNavigationDirtyArea> DirtyAreas
然后在 void UNavigationSystemV1::Tick(float DeltaSeconds) 內(nèi),調(diào)用
- RebuildDirtyAreas(DeltaSeconds)
- DefaultDirtyAreasController.Tick
- NavData->RebuildDirtyAreas(DirtyAreas)
將這些 DirtyArea 傳遞給 ANavigationData 的 FNavDataGenerator 處理
以Recast為例,就是將與 FNavigationDirtyArea 相交的 Tile 進(jìn)行重建
注意,RebuildDirtyAreas(DeltaSeconds) 有一個(gè)前提是 IsNavigationBuildingLocked() == false,而當(dāng)編輯器設(shè)置內(nèi)的 Update Navigation Automatically 為 False 時(shí),NavBuildingLockFlags 會加上 ENavigationBuildLock::NoUpdateInEditor,所以這種情況下除非主動調(diào)用 RebuildAll,也就是 Build - Build Path,否則NavData是不會變化的
動態(tài)修改尋路
DynamicModifiersOnly
將ProjectSetting內(nèi),NavigationMesh的RuntimeGeneration改為DynamicModifiersOnly
針對會移動的障礙,將障礙的StaticMeshComponent的Can Ever Affect Navigation改為False,并且給障礙加上NavModifierComponent。
注意,由于是障礙物,所以需要把NavModifierComponent的AreaClass改為NavArea_Null。
優(yōu)化動態(tài)修改尋路
https://zhuanlan.zhihu.com/p/566846141
大世界下尋路網(wǎng)格的使用
1 老辦法
直接加載所有的塊,然后build path,注意,為了避免之后加載塊導(dǎo)致的build path,在編輯器設(shè)置內(nèi)關(guān)閉自動更新導(dǎo)航
2 只在周圍生成
只在Invoker周圍動態(tài)生成尋路數(shù)據(jù)
參考:
https://www.youtube.com/watch?v=DMe536X4IT0
https://www.youtube.com/watch?v=Smuy2d7y7mA&list=PLNTm9yU0zou7kKcN7091Rdr322Qge5LNA&index=47
第一個(gè)視頻 核心是開啟這個(gè)選項(xiàng)(還是需要尋路體積的)
下面的參數(shù)是更新周期
然后給中心物體(Pawn)加上Navigation Invoker Component
這樣子就會在這個(gè)物體周圍生成尋路數(shù)據(jù)了
內(nèi)部有兩個(gè)Tile Generation Radius和Tile Removal Radius,表示當(dāng)區(qū)域進(jìn)入Generation 范圍就會生成,離開Removal 范圍就會刪除
第二個(gè)視頻是說,如果目標(biāo)太遠(yuǎn)了,就在周圍找一個(gè)目標(biāo)方向的點(diǎn)過去,靠這種方式慢慢接近
3 world-partitioned做法
操作
https://docs.unrealengine.com/5.0/en-US/world-partitioned-navigation-mesh/
https://docs.unrealengine.com/5.1/en-US/world-partition-in-unreal-engine/
Command: UnrealEditor.exe “C:\Users\user.name\Documents\Unreal Projects\MyProject\MyProject.uproject” “/Game/ThirdPersonBP/Maps/OpenWorldTest” -run=WorldPartitionBuilderCommandlet -AllowCommandletRendering -builder=WorldPartitionNavigationDataBuilder -SCCProvider=None
原理
生成的尋路數(shù)據(jù)會保存到ChunkActor,對于Recast來說就是對應(yīng)區(qū)域內(nèi)的FRecastTileData
當(dāng)區(qū)塊被加載的時(shí)候,會同時(shí)加載ANavigationDataChunkActor,這個(gè)時(shí)候會對每個(gè)尋路數(shù)據(jù),調(diào)用OnStreamingNavDataAdded
以Recast為例,會調(diào)用URecastNavMeshDataChunk::AttachTiles,對于存儲在ChunkActor內(nèi)的所有FRecastTileData, 使用NavMesh->addTile附加到NavMesh內(nèi)
總結(jié)
以上是生活随笔為你收集整理的Unreal 寻路网格的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 交换机千兆和百兆对网速影响_交换机千兆和
- 下一篇: 人人权限系统本地部署