看板 GameDesign 關於我們 聯絡資訊
網頁版 https://yekdniwue.blogspot.tw/2018/02/unreal-avoidance.html 在上篇 我們提到使用Unreal內建的Detour迴避有一些限制 這些限制主要是純BP專案無法透過C++修改行為造成的。 所以本篇是以C++專案為基礎,說明如果要使用Detour的功能, 可能要做哪些修改才能達到。 需要注意的是這篇文章為了重現當初改寫時遇到的過程,會有大量的文字描述, 沒興趣的話應該會啃不下去。 但是裡面有一些遇到問題的解法,對解題過程有興趣的人可以看看, 或是有更好的建議也歡迎~ 本篇會介紹下面幾個項目,可以先看看有沒有你要的內容再繼續~ 1. 為什麼要複寫CrowdManager 2. 繼承並複寫CrowdManager 3. 在執行時期更改AvoidanceGroup *****為什麼要複寫CrowdManager***** 這是個很冗長的流程,當初我發現RVO可以動態透過API修改Avoidance Group, 但是用CrowdPathFollowingComponent(以下簡稱CPFC)卻不行時,我也是嚇了一跳。 於是我跑去追CPFC的程式碼,發現要修改Detour迴避行為的函式 全部都被定義為private(圖1), 然後標頭檔的最後標示了CPFC的friend class是 CrowdManager。 顯示即使繼承CPFC也沒辦法改寫迴避的行為, 設定全部都必須要透過CrowdManager處理。 [圖1.] 圖1. 設定Detour的函式都是private。 然後跑去CrowdManager挖程式碼,卻發現CPFC那些設定相關的函式都沒被用到... 代表要繼承CrowdManager才能達到我希望能修改迴避參數的目標。 *****繼承並複寫CrowdManager***** 首先當然就是先繼承CrowdManager: 在Unreal Editor->New C++ Class->Show all classes 輸入CrowdManager,並選擇CrowdManager,輸入名字與路徑就可以完成繼承。 在Edit->Project Settings->Engine->NavigationSystem內有CrowdManagerClass 將此欄位指向剛剛創好的MyCrowdManager。可參考圖2 圖2. 在Engine設定CrowdManagerClass為自己複寫的class。 然後你就可以使用自定義的CrowdManager了........................... . . . . . . . . . . 如果是這樣我幹嘛寫這篇!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 由於這部份有點複雜,我也是追了一陣子的程式碼才找到原因 (其實是有點久我忘記細節) 詳情可以用中斷點追一下NavigationSystem.cpp裡面的 constructor,InitializeForWorld, PostInitProperties,CreateCrowdManager這幾個函式裡面 有關CrowdManagerClass的部份。 總之那個CrowdManagerClass雖然開成可編輯的項目,實際上根本沒作用, 程式執行過程中不會吃你設定的值。 所以回過頭來,該如何讓我們的CrowdManager生效呢? 我找到這篇討論有說明在不修改引擎程式碼的狀況下,如何使自定義的CrowdManager起作 用 https://answers.unrealengine.com/questions/100941/ucrowdfollowingcomponent-51st-bot-does-not-move.html?childToView=102163#answer-102163 縮短網址: https://goo.gl/HR12Aj 這邊就直接step by step說明: 1. 繼承NavigationSystem。 2. 複寫NavigationSystem::CreateCrowdManager() 直接在函式內生成你的CrowdManager並傳進SetCrowdManager: SetCrowdManager(NewObject<UCrowdManagerBase>(this, UMyCrowdManager::StaticClass())); 3. 到Engine/Config/DefaultEngine.ini加下面兩行 [/Script/Engine.Engine] NavigationSystemClassName=/Script/[YourProjectName].[NavigationClassName] 4.關掉Editor重開,就可以試試看你的CrowdManager是不是運作了~ *****在執行時期更改AvoidanceGroup***** 複寫的CrowdManager之後,所有要對CPFC設定的行為就都可以達到了,大致上就是寫類似 的函式: void UMyCrowdManager::SetAvoidanceGroup( UCrowdFollowingComponent* AgentComponent, int32 GroupFlags, bool bUpdateAgent = true) { AgentComponent->SetAvoidanceGroup(GroupFlags, bUpdateAgent); } void UMyCrowdManager::SetCrowdSlowdownAtGoal( UCrowdFollowingComponent* AgentComponent, bool bEnable, bool bUpdateAgent) { AgentComponent->SetCrowdSlowdownAtGoal(bEnable, bUpdateAgent); } 有時候為了方便能夠能在blueprint作處理會比較好, 而CrowdManager好像在bp是拿不到的, 反正都C++了就直接作一個吧~ 定義 UFUNCTION(BlueprintCallable, Category = "MyCrowdManager") static UCrowdManagerBase* GetMyCrowdManager(UObject* WorldContextObject); 實作 UCrowdManagerBase* UMyCrowdManager::GetMyCrowdManager( UObject* WorldContextObject) { UNavigationSystem* navSystem = WorldContextObject->GetWorld()->GetNavigationSystem(); return navSystem->GetCrowdManager(); } 後續其實還是有東西可以寫,大致上是Detour有提供視覺化的Debug功能, 可以介紹如何開啟以及觀察;如何設定/調整自定義的迴避樣板; 如何迴避玩家。 不過這次就先寫到這裡就好~ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 122.116.41.55 ※ 文章網址: https://www.ptt.cc/bbs/GameDesign/M.1519843307.A.16E.html
coolrobin: 推推,坐等續集 www 03/01 20:17
damody: 123 03/02 09:45
breakself: 321 03/06 10:34
※ 編輯: yekdniw (59.120.146.90 臺灣), 07/15/2020 11:08:10