[程式] Unreal Avoidance系統(下)

作者: yekdniw (yekdniw)   2018-03-01 02:41:39
網頁版
https://yekdniwunrealengine.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功能,
可以介紹如何開啟以及觀察;如何設定/調整自定義的迴避樣板;
如何迴避玩家。
不過這次就先寫到這裡就好~
作者: coolrobin (泳圈)   2018-03-01 20:17:00
推推,坐等續集 www
作者: damody (天亮damody)   2018-03-02 09:45:00
123
作者: breakself (A3)   2018-03-06 10:34:00
321

Links booklink

Contact Us: admin [ a t ] ucptt.com