Get Distance at Location Along Spline

You have to upload an image to the internet, there’s an upload option if you use the image button. We can’t see a local file.

Hi, wouldn’t something like this achieve what everyone wants?



float DistanceInSplineOf(FVector aWorldLocation)
{
    float locationInputKey = splineMeshComponent->FindInputKeyClosestToWorldLocation(aWorldLocation);
    float segmentEndParameter = locationInputKey / splineMeshComponent->GetNumberOfSplinePoints();//so it's a value between 0 and 1. The spline is a parametrized curve.
    
    GEngine->AddOnScreenDebugMessage(-1, 50.0f, FColor::Orange, FString::Printf(TEXT("Input key nearest to world location: %f"), locationInputKey));
    GEngine->AddOnScreenDebugMessage(-1, 50.0f, FColor::Yellow, FString::Printf(TEXT("Segment end parameter: %f."), segmentEndParameter));
    float distanceAlongSpline = splineMeshComponent->SplineCurves.GetSegmentLength(0, segmentEndParameter);
    //zero represents the start of the spline.
    //if you need to calculate distance treating the spline as a closed loop, use:
    //splineMeshComponent->SplineCurves.GetSegmentLength(0, segmentEndParameter, true);
    
    GEngine->AddOnScreenDebugMessage(-1, 50.0f, FColor::Green, FString::Printf(TEXT("Distance along spline of a world location: %f"), distanceAlongSpline));
    return distanceAlongSpline;
}


Ok, that doesn’t work. Maybe something like this?



float DistanceAlongSplineOf(FVector aWorldLocation)
{
    float locationInputKey = splineMeshComponent->FindInputKeyClosestToWorldLocation(aWorldLocation);
    
    int reparametrizationStepsPerSegment = 10;
    float distanceAlongSpline = splineMeshComponent->SplineCurves.ReparamTable.Points[FMath::RoundToInt(locationInputKey * reparametrizationStepsPerSegment)].InVal;
    //10 is the magic number UE4 uses to make the ReparamStepsPerSegment. It's set at construction and never changed.
    //this is based on GetDistanceAlongSplineAtSplinePoint, it uses the same approach.
    
    UE_LOG(LogTemp, Log, TEXT("location: %s."), *aWorldLocation.ToString());
    UE_LOG(LogTemp, Log, TEXT("location input key: %f."), locationInputKey);
    UE_LOG(LogTemp, Log, TEXT("location distance to spline: %f."), distanceAlongSpline);
    return distanceAlongSpline;
}


More accurate:



float DistanceAlongSplineOf(FVector aWorldLocation)
{
    float locationInputKey = splineMeshComponent->FindInputKeyClosestToWorldLocation(aWorldLocation);
    int32 splinePointFromInputKey = FMath::TruncToInt(locationInputKey);
    float remainingSegmentParameter = locationInputKey - splinePointFromInputKey;
    
    float distanceToSplinePoint = splineMeshComponent->GetDistanceAlongSplineAtSplinePoint(splinePointFromInputKey);
    
    float remainingSegmentLength = splineMeshComponent->SplineCurves.GetSegmentLength(splinePointFromInputKey, remainingSegmentParameter, true);
    
    float distanceAlongSpline = distanceToSplinePoint + remainingSegmentLength;
    
    UE_LOG(LogTemp, Log, TEXT("location: %s."), *aWorldLocation.ToString());
    UE_LOG(LogTemp, Log, TEXT("location input key: %f."), locationInputKey);
    UE_LOG(LogTemp, Log, TEXT("location distance to spline: %f."), distanceAlongSpline);
    
     return distanceAlongSpline;
}


Just in case anyone’s still having an issue finding their distance along a spline in blueprint, here’s a working simple solution:

11 Likes

Thank mate! That’s gorgeous and makes me understand a bit more about Blueprints (long path ahead).

Thank you so much WillWeaver and Aakrasia for the blueprint examples and everyone who posted earlier in this thread! ~^_^~

The information and examples were a huge help in debugging an issue I was having trying to get a object to snap to a spline upon hit (It worked on straight splines, but was always off on curved ones).

The more accurate methods are a bit above my current skill level (Along with most anything that involves actual code), so I definitely appreciate the simplified blueprint methods that I could use right out of the box! ^_~