Hi there,
A question to anyone into tuning A* using the existing QueryFilter classes:
Q: Did anyone try overriding “dtQueryFilter” or similar A* cost/heuristic implementation changes without touching Engine level code like described below?
Details:
I recently tuned existing A related methods* by implementing my own set of UNavigationQueryFilter and its helpers FRecastQueryFilter / dtQueryFilter.
( … and then, in my case to influence A* run-time, calling “setHeuristicScale()” on my own dtMyQueryFilter instance and implementing “dtMyQueryFilter::getVirtualCost()” to add per-node cost calculations and a few custom rules. )
Actual code changes I wanted to investigate further or avoid:
1. Engine code change I’d like to avoid: I added that virtual keyword below to modify “UNavigationQueryFilter::GetQueryFilter()”, otherwise I couldn’t find a good way to create and return my own FNavigationQueryFilter class instance from inside any of the existing GetQueryFilter() calls:
// in AI/Navigation/NavFilters/NavigationQueryFilter.h
class ENGINE_API UNavigationQueryFilter : public UObject
{
...
/** get filter for given navigation data and initialize on first access */
virtual FSharedConstNavQueryFilter GetQueryFilter(const ANavigationData& NavData, const UObject* Querier) const;
);
2. Another engine code “issue”, code I would prefer to re-write to be polymorphic, or at least allow class derivates:
The original, unchanged Engine code will cast to “FRecastQueryFilter / dtQueryFilter” (the Engine’s original classes/implementations), i.e. this code is not written exactly with deriving those classes in mind:
In “FPImplRecastNavmesh::FindPath()”:
// see AI\Navigation\PImplRecastNavMesh.cpp", Line 788:
const FRecastQueryFilter* FilterImplementation = (const FRecastQueryFilter*)(InQueryFilter.GetImplementation());
const dtQueryFilter* QueryFilter = FilterImplementation->GetAsDetourQueryFilter();
This is kind of working but since “const FRecastQueryFilter*” and “GetAsDetourQueryFilter()” or the context of any surrounding code might still change I feel tempted to remove casts and make methods like “GetAsDetourQueryFilter()” virtual to have a cleaner interface, i.e. caller/callee agree on using FRecastQueryFilter/dtQueryFilter base class or derivates, but don’t cast and/or assume specific classes to exist here at run-time.
Cheers,