日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unreal 寻路网格

發布時間:2023/12/20 编程问答 80 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unreal 寻路网格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • Agent 的挑選
    • Nav Data是什么
    • NavLinkProxy是什么
    • 尋路網格算法
    • Build Path 流程
    • 虛幻Recast dtNavMesh Build流程
    • 修改尋路網格
    • 動態修改尋路
      • DynamicModifiersOnly
    • 優化動態修改尋路
    • 大世界下尋路網格的使用
      • 1 老辦法
      • 2 只在周圍生成
      • 3 world-partitioned做法
        • 操作
        • 原理

Agent 的挑選

在項目設置內,Navigation System 內可以配置一些Agents

在尋路過程中,使用移動組件內的配置去匹配所有Agents

具體的函數如下:

const ANavigationData* UNavigationSystemV1::GetNavDataForProps(const FNavAgentProperties& AgentProperties) const

匹配的規則:

  • 首先判斷 Preferred Nav Data 是否匹配:

    return (PreferredNavData == Other.PreferredNavData || PreferredNavData.IsNull() || Other.PreferredNavData.IsNull());
  • 然后用 AgentRadius 和 AgentHeight 進行匹配(默認-1,表示使用膠囊體),挑出最匹配的那個

    • 單項更優判斷:較大的優先(Agent 比目標大,至少不會出現卡住的情況),都比目標大或者小的情況下,較接近的優先
    • 若不符合兩項都較優或相同,且之前的Agent不合法(兩項有一項是小于目標的),則先使用半徑判斷,若相同再用高度判斷,只有有一項是較優則替換
    • 所以,Agent的設置和實際的相同或者大一些
    • 注意這里兩項相同的情況也會替換,而List本身是項目設置內的逆序,所以默認的Agent排在上面
    ExcessRadius = NavIt.AgentRadius - AgentProperties.AgentRadius; ExcessHeight = bSkipAgentHeightCheckWhenPickingNavData ? 0.f : (NavIt.AgentHeight - AgentHeight);const bool bExcessRadiusIsBetter = ((ExcessRadius == 0) && (BestExcessRadius != 0)) || ((ExcessRadius > 0) && (BestExcessRadius < 0))|| ((ExcessRadius > 0) && (BestExcessRadius > 0) && (ExcessRadius < BestExcessRadius))|| ((ExcessRadius < 0) && (BestExcessRadius < 0) && (ExcessRadius > BestExcessRadius)); const bool bExcessHeightIsBetter = ((ExcessHeight == 0) && (BestExcessHeight != 0))|| ((ExcessHeight > 0) && (BestExcessHeight < 0))|| ((ExcessHeight > 0) && (BestExcessHeight > 0) && (ExcessHeight < BestExcessHeight))|| ((ExcessHeight < 0) && (BestExcessHeight < 0) && (ExcessHeight > BestExcessHeight)); const bool bBestIsValid = (BestExcessRadius >= 0) && (BestExcessHeight >= 0); const bool bRadiusEquals = (ExcessRadius == BestExcessRadius); const bool bHeightEquals = (ExcessHeight == BestExcessHeight);bool bValuesAreBest = ((bExcessRadiusIsBetter || bRadiusEquals) && (bExcessHeightIsBetter || bHeightEquals)); if (!bValuesAreBest && !bBestIsValid) {bValuesAreBest = bExcessRadiusIsBetter || (bRadiusEquals && bExcessHeightIsBetter); }if (bValuesAreBest) {BestFitNavAgent = NavIt;BestExcessHeight = ExcessHeight;BestExcessRadius = ExcessRadius; }

Nav Data是什么

在 Build Path 時,World 內會為每一個 Agent 生成一份 NavigationData,用于這種類型角色的尋路。具體流程是:A 在尋路時,根據(PreferredNavData、AgentRadius、AgentHeight)找到最符合的 Agent,然后使用該 Agent 對應的 NavigationData,進行路徑搜索,最后找出 N 個點,就是尋找到的路徑,然后 AI 就按照這條路徑操縱移動組件進行移動(移動流程參考UE4:AI‘s MoveTo——代碼分析)

而每個 Agent 有自己的 Nav Data Class,也就是說同樣體型不同 Nav Data Class 的情況下需要兩個 Agent,以飛行為例,我們需要兩個 Agent,一個Walk,一個Fly,當需要進行飛行尋路時,就需要找到 Fly 這個 Agent。而 Fly Agent 生成的 NavigationData,就是用于飛行尋路的基礎數據。

NavLinkProxy是什么

有一些游戲機制(例如傳送門),使得我們的路徑沒法使用單純自動生成的尋路網格,需要增加一些處理。這種情形下我們會用到NavLinkProxy,將兩個點之間聯通(可選單向),我們的尋路就會將這兩個點聯通。

當AI到達點A時,會觸發NavLinkProxy的Receive Smart Link Reached,這里我們可以自定義AI所需要觸發的函數,例如響應傳說。

尋路網格算法

https://zhuanlan.zhihu.com/p/359376662

https://zhuanlan.zhihu.com/p/74537236

Build Path 流程

在Build - Build Path,進入到UNavigationSystemV1::Build()

UNavigationSystemV1::Build()

  • void UNavigationSystemV1::SpawnMissingNavigationData()
  • void UNavigationSystemV1::RebuildAll(bool bIsLoadTime)
  • FNavDataGenerator::RebuildAll

就是對每個NavData,運行NavDataGenerator的RebuildAll函數

虛幻Recast dtNavMesh Build流程

https://docs.unrealengine.com/4.27/en-US/API/Runtime/Navmesh/Detour/dtNavMesh/

修改尋路網格

將 DirtyArea 塞入 DirtyAreasController 的 TArray<FNavigationDirtyArea> DirtyAreas

然后在 void UNavigationSystemV1::Tick(float DeltaSeconds) 內,調用

  • RebuildDirtyAreas(DeltaSeconds)
  • DefaultDirtyAreasController.Tick
  • NavData->RebuildDirtyAreas(DirtyAreas)

將這些 DirtyArea 傳遞給 ANavigationData 的 FNavDataGenerator 處理

以Recast為例,就是將與 FNavigationDirtyArea 相交的 Tile 進行重建


注意,RebuildDirtyAreas(DeltaSeconds) 有一個前提是 IsNavigationBuildingLocked() == false,而當編輯器設置內的 Update Navigation Automatically 為 False 時,NavBuildingLockFlags 會加上 ENavigationBuildLock::NoUpdateInEditor,所以這種情況下除非主動調用 RebuildAll,也就是 Build - Build Path,否則NavData是不會變化的

動態修改尋路

DynamicModifiersOnly

將ProjectSetting內,NavigationMesh的RuntimeGeneration改為DynamicModifiersOnly

針對會移動的障礙,將障礙的StaticMeshComponent的Can Ever Affect Navigation改為False,并且給障礙加上NavModifierComponent。

注意,由于是障礙物,所以需要把NavModifierComponent的AreaClass改為NavArea_Null。

優化動態修改尋路

https://zhuanlan.zhihu.com/p/566846141

大世界下尋路網格的使用

1 老辦法

直接加載所有的塊,然后build path,注意,為了避免之后加載塊導致的build path,在編輯器設置內關閉自動更新導航

2 只在周圍生成

只在Invoker周圍動態生成尋路數據

參考:
https://www.youtube.com/watch?v=DMe536X4IT0
https://www.youtube.com/watch?v=Smuy2d7y7mA&list=PLNTm9yU0zou7kKcN7091Rdr322Qge5LNA&index=47

第一個視頻 核心是開啟這個選項(還是需要尋路體積的)

下面的參數是更新周期

然后給中心物體(Pawn)加上Navigation Invoker Component

這樣子就會在這個物體周圍生成尋路數據了

內部有兩個Tile Generation Radius和Tile Removal Radius,表示當區域進入Generation 范圍就會生成,離開Removal 范圍就會刪除

第二個視頻是說,如果目標太遠了,就在周圍找一個目標方向的點過去,靠這種方式慢慢接近

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

原理

生成的尋路數據會保存到ChunkActor,對于Recast來說就是對應區域內的FRecastTileData

當區塊被加載的時候,會同時加載ANavigationDataChunkActor,這個時候會對每個尋路數據,調用OnStreamingNavDataAdded

以Recast為例,會調用URecastNavMeshDataChunk::AttachTiles,對于存儲在ChunkActor內的所有FRecastTileData, 使用NavMesh->addTile附加到NavMesh內

總結

以上是生活随笔為你收集整理的Unreal 寻路网格的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。