Why does it set my character to the beginning of the spline?

I don’t understand why my character keeps starting at the beginning of the spline even though I’m grabbing and setting the point where the sphere trace hits the rail.

Here is a video of the issue: Screen capture - d8ea85f7cdcbdcf7defc684305539c3a - Gyazo

Here is my code for checking for the grind where the start point is being grabbed:

void AMainPlayer::GrindCheck(const FInputActionValue& Value) {

	if (!isGrinding) {


		FVector startLoc = GetActorLocation() + FVector(0, 0, -75.0f);
		FVector endLoc = startLoc;
		float radius = 30.0f;

		FHitResult hitResult;
		TArray<TEnumAsByte<EObjectTypeQuery>> CollisionObjects;
		CollisionObjects.Add(UEngineTypes::ConvertToObjectType(ECC_GameTraceChannel1));
		bool hit = UKismetSystemLibrary::SphereTraceSingleForObjects(this, startLoc, endLoc, radius, CollisionObjects, false, TArray<AActor*>(), EDrawDebugTrace::ForDuration, hitResult, true, FLinearColor::Red, FLinearColor::Green, 5.0f);

		if (hit) {
			grindLoc = hitResult.Location;
			AActor* actorHit = hitResult.GetActor();
			grindSpline = actorHit->FindComponentByClass<USplineComponent>();

			if (grindSpline != nullptr) {
				
				distAlongSpline = grindSpline->FindInputKeyClosestToWorldLocation(hitResult.Location);
			
				UE_LOG(LogTemp, Warning, TEXT("Spline Point %f"), distAlongSpline);
				isGrinding = true;
			}


		}
	}

}

And here is my grinding function:

void AMainPlayer::Grinding(float DeltaTime) {


	float splineLength = grindSpline->GetSplineLength();

	distAlongSpline += speed * DeltaTime;

	FVector NewLoc = grindSpline->GetLocationAtDistanceAlongSpline(distAlongSpline, ESplineCoordinateSpace::World);
	SetActorLocation(NewLoc);

	FRotator NewRot = grindSpline->GetRotationAtDistanceAlongSpline(distAlongSpline, ESplineCoordinateSpace::World);
	SetActorRotation(NewRot);


}

I think I fixed it with

distAlongSpline = grindSpline->FindInputKeyClosestToWorldLocation(hitResult.Location) * grindSpline->GetSplineLength();

But I’m not really sure.

Hi LockeKosta,

The InputKey is different than the SplinePoint and Distance - you can get the location and rotation from the InputKey with:

Also, the InputKey is not guaranteed to be between 0 and 1.

Maybe that’s why it feels wonky? What would be a better way to detect the closest spot on the spline from the sphere trace and start there?

If you’re in UE5 or above, you can use:

 GetDistanceAlongSplineAtSplineInputKey(MyInputKey)

so:

float myKey=grindSpline->FindInputKeyClosestToWorldLocation(hitResult.Location);
distAlongSpline=grindSpline->GetDistanceAlongSplineAtSplineInputKey(myKey);

And this is cleaner/more precise? It does kinda seem that way but my other method was visually working the same. Would it have broken on splines with added points?

Asking cause I’m trying to learn how to fish more than just catch this one. Struggling a bit to completely wrap my head around exactly how splines are working in Unreal and while there are plenty of videos on the topics, they all seem to sort of “cheat” or use them much more stringently than what I’m trying to do.

In the “GetDistanceAlongSplineAtSplineInputKey()” method it is getting the distance from the key you are - so is working in a similar way to what you’ve done - I would use the Epic routines though (check out the source for that method).

Basically, the input key should have the index in the whole number, and the fraction should be amount between that index and the next. In practice I’ve seen input keys range between 0.0 and 1.0 though so I can’t explain those.

Gotchya. I’ll continue to look into and study it further as I refine the system. I greatly appreciate your assistance and direction.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.