[程式] 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