Is it possible to somehow pass a “max cost” to FindPathToLocationSynchronously (or some other similar function) so that it cuts off the path once the cost is reached (even if the actual destination hasn’t been reached). Basically I m trying to implement action-point style movement and would the path to abort when it reaches character’s AP value.
Thanks for your reply. One more question - i can’t just simply cut by percentage , right ? For example - if I find out that leftover AP (let’s say 1000) to path cost (let’s say 2000) ratio is 50%, I can’t just cut the path at its 50% of length, since the cost is not necessarily linear (due to possibly varying area costs along the path length). For example it could be that the first 50% of the path cost only 500 but the remaining 50% of the path cost 1500 due to the area cost. So I 'm gonna have to write some recursive function that keeps adjusting the path end up and down until it reaches the correct value right ? For example - the function would try to first adjust the end to 50% and requery. Then it would realize that only costs 500 AP, but the char had 1000AP and wanted to go further. Then the function would query with end set at 75% of the original path and check that for cost. If the cost is still lower it would query with 87.5% , if higher it would query with 62.5%, and so on until it gets close enough. Is that basically what I’d need to do ?
Yeah, you need to implement this yourself. I’d suggest using a for-loop though, starting from the beginning of the path and summing up subsequent steps’ cost. Mind that if you’re string-pulling the path (which is the default behavior) you may end up with very long path segments, which would affect your cost calculations, and you’ll need to add intermediate points along the path to properly, precisely calculate path’s AP cost.
Ok, I think I got it. Here’s the code if anyone else looks for this):
float GetPathCost(UNavigationPath* path)
{
// in some cases GetPathCost returns 0, so using len if that happens.
float cost = path->GetPathCost();
if (cost == 0)
cost = path->GetPathLength();;
return cost;
}
void GetPathSubpoints(UNavigationPath* path, TArray<FVector>& subPoints)
{
int minStepAmount = 100;
for (int i = 0; i < path->PathPoints.Num() - 1; i++)
{
FVector pathDir = path->PathPoints[i + 1] - path->PathPoints[i];
float len = pathDir.Size();
int numSubPoints = len / minStepAmount;
for (int z = 0; z < numSubPoints; z++)
{
float t = (float)z / (float)numSubPoints;
FVector location = path->PathPoints[i] + pathDir * t;
subPoints.Add(location);
}
}
subPoints.Add(path->PathPoints[path->PathPoints.Num() - 1]);
}
TArray<UNavigationPath*> FindPathAndFitToActionPoints(UWorld* world, const FVector& start, const FVector& end, int ap )
{
TArray<UNavigationPath*> navPathArray;
UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(world);
// get the desired path and store in navPath array.
auto path = NavSys->FindPathToLocationSynchronously(world, start, end);
navPathArray.Add(path);
float cost = GetPathCost(path);
int minStepAmount = 100;
int costUnitsPerAP = 100;
int apForPath = cost / costUnitsPerAP;
// if we already have enough AP then just get out of here
if (ap >= apForPath)
return navPathArray;
float totalPathLen = 0;
TArray<FVector> subPoints;
GetPathSubpoints(path, subPoints);
subPoints.Add(path->PathPoints[path->PathPoints.Num()-1]);
UNavigationPath* prevPath = nullptr;
for (int i = 1; i < subPoints.Num(); i++)
{
path = NavSys->FindPathToLocationSynchronously(world, start, subPoints[i]);
float cost = GetPathCost(path);
if ( (cost / costUnitsPerAP) > ap)
break;
else prevPath = path;
}
navPathArray.Add(prevPath);
return navPathArray;
}
I posted the solution below if anyone has a similar question.
Btw - while on this topic. Any ideas why getpathcost returns 0 sometimes. I did some brief debugging and looks to be returning 0 if the final path is in the same segment or somethign along those lines. What’s the reasoning behind that ?