Figured I might as well update this eons old thread… here’s how to get the link type (i.e. the “Nav Area Class”) in this case, I check if the class is of the “Ladder” type (which I’d declared earlier as a new UNavArea class). I then teleport to the other end of the ladder if it is (basically, the navlink has two points, so find the farthest one from us and teleport to it).
Obviously you’d want to transition into some kind of animation state machine thing if you were doing the ladder case.
void UTacticalPathFollowingComponent::OnNavNodeChanged(NavNodeRef NewPolyRef, NavNodeRef PrevPolyRef, int32 CorridorSize)
{
Super::OnNavNodeChanged(NewPolyRef, PrevPolyRef, CorridorSize);
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Emerald, *FString::Printf(TEXT("TacPathFollow: Changing Nav Poly")));
}
FNavMeshPath* NavPath = Path.IsValid() ? Path->CastPath<FNavMeshPath>() : NULL;
if (NavPath)
{
ARecastNavMesh* RecastNavData = Cast<ARecastNavMesh>(NavPath->GetNavigationDataUsed());
if (RecastNavData != nullptr)
{
FVector PtA, PtB;
const bool bStartIsNavLink = RecastNavData->GetLinkEndPoints(NewPolyRef, PtA, PtB);
if (bStartIsNavLink)
{
// path for next movement is a nav link.. so see how to traverse it by querying the associated class? Seems weird.
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Emerald, *FString::Printf(TEXT("TacPathFollow: New Nav Poly has Custom Link")));
}
uint32 id = RecastNavData->GetPolyAreaID(NewPolyRef);
FNavMeshNodeFlags Flags;
if (RecastNavData->GetPolyFlags(NewPolyRef, Flags))
{
const UClass* AreaClass = RecastNavData->GetAreaClass(Flags.Area);
const UNavArea* DefArea = AreaClass ? ((UClass*)AreaClass)->GetDefaultObject<UNavArea>() : NULL;
if (DefArea)
{
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(2, 5.0f, FColor::Emerald, *FString::Printf(TEXT("TacPathFollow: Area ID: %d Area Class: %s"),id,*DefArea->GetName()));
}
//const UNavArea_Ladder * LadderArea = AreaClass ? ((UClass*)AreaClass)->GetDefaultObject<UNavArea_Ladder>() : NULL;
if (AreaClass->IsChildOf(UNavArea_Ladder::StaticClass()))
{
AAIController * controller = Cast<AAIController>(GetOwner());
if (controller && controller->GetControlledPawn())
{
APawn * pawn = controller->GetControlledPawn();
// find the closest point in the navlink to us.. then teleport to the other one
float distToA = (pawn->GetActorLocation() - PtA).SizeSquared();
float distToB = (pawn->GetActorLocation() - PtB).SizeSquared();
if (distToB > distToA)
{
//GetOwner()->SetActorLocation(PtB + FVector(0.0f,0.0f,200.0f));
FVector loc = PtB + FVector(0.0f, 0.0f, pawn->GetDefaultHalfHeight());
DrawDebugSphere(GetWorld(), loc, 40.0f, 8, FColor::Red, false, 5.0f);
bool bMoved = pawn->TeleportTo(loc, GetOwner()->GetActorRotation());
}
else
{
//GetOwner()->SetActorLocation(PtA + FVector(0.0f,0.0f,200.0f));
FVector loc = PtA + FVector(0.0f, 0.0f, pawn->GetDefaultHalfHeight());
DrawDebugSphere(GetWorld(), loc, 40.0f, 8, FColor::Cyan, false, 5.0f);
pawn->TeleportTo(loc, GetOwner()->GetActorRotation());
}
}
}
}
};
}
}
}
}