diff --git a/Source/RWTHVRQuickStart/Private/PointOfInterestManager.cpp b/Source/RWTHVRQuickStart/Private/PointOfInterestManager.cpp
index 827049531053be02a3e3282b01843d21c10ec1c3..b761849041536395ff26e4572774b223d165ddcc 100644
--- a/Source/RWTHVRQuickStart/Private/PointOfInterestManager.cpp
+++ b/Source/RWTHVRQuickStart/Private/PointOfInterestManager.cpp
@@ -30,7 +30,7 @@ void APointOfInterestManager::TickActor(float DeltaTime, enum ELevelTick TickTyp
 void APointOfInterestManager::AddPointOfInterest()
 {
 	APointOfInterest* POI = static_cast<APointOfInterest*>(GetWorld()->SpawnActor(APointOfInterest::StaticClass()));
-	
+
 	POI->GetRootComponent()->TransformUpdated.AddLambda([this](USceneComponent*, EUpdateTransformFlags, ETeleportType)
 	{
 		UpdateSpline();
@@ -99,6 +99,8 @@ void APointOfInterestManager::StartCameraRide()
 {
 	CameraRideStart = UGameplayStatics::GetTimeSeconds(this);
 	CameraRideEnd = CameraRideStart + SplineComponent->Duration;
+	CurrentUpdate = 0;
+	DurationInUpdates = static_cast<int>(SplineComponent->Duration * CameraRideSecondsToUpdates);
 
 	IsRidingCamera = true;
 }
@@ -161,7 +163,7 @@ void APointOfInterestManager::ProgressCameraRide()
 {
 	double Current = UGameplayStatics::GetTimeSeconds(this);
 	float SecondsSinceStart = Current - CameraRideStart;
-	UE_LOGFMT(POIManagerLog, VeryVerbose, "");
+	CurrentUpdate++;
 
 	APawn* Pawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
 	if (!Pawn)
@@ -169,19 +171,40 @@ void APointOfInterestManager::ProgressCameraRide()
 		UE_LOGFMT(POIManagerLog, Warning, "Attempted to move player pawn but no pawn found to move.");
 		return;
 	}
-	if (Current < CameraRideEnd)
+	if (MakeCameraRideProgressionConstantBetweenTicks)
 	{
-		FVector Location = SplineComponent->GetLocationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
-		FRotator Rotation = SplineComponent->GetRotationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
-		Rotation.Pitch = 0;
-		Rotation.Roll = 0;
-
-		Pawn->Controller->SetControlRotation(Rotation);
-		Pawn->SetActorLocationAndRotation(Location, Rotation);
+		if (CurrentUpdate < DurationInUpdates)
+		{
+			float CurrentTime = 1.0f * CurrentUpdate / CameraRideSecondsToUpdates;
+			FVector Location = SplineComponent->GetLocationAtTime(CurrentTime, ESplineCoordinateSpace::World);
+			FRotator Rotation = SplineComponent->GetRotationAtTime(CurrentTime, ESplineCoordinateSpace::World);
+			Rotation.Pitch = 0;
+			Rotation.Roll = 0;
+
+			Pawn->Controller->SetControlRotation(Rotation);
+			Pawn->SetActorLocationAndRotation(Location, Rotation);
+		}
+		else
+		{
+			CameraRideEnded();
+		}
 	}
 	else
 	{
-		CameraRideEnded();
+		if (Current < CameraRideEnd)
+		{
+			FVector Location = SplineComponent->GetLocationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
+			FRotator Rotation = SplineComponent->GetRotationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
+			Rotation.Pitch = 0;
+			Rotation.Roll = 0;
+
+			Pawn->Controller->SetControlRotation(Rotation);
+			Pawn->SetActorLocationAndRotation(Location, Rotation);
+		}
+		else
+		{
+			CameraRideEnded();
+		}
 	}
 }
 
diff --git a/Source/RWTHVRQuickStart/Public/PointOfInterestManager.h b/Source/RWTHVRQuickStart/Public/PointOfInterestManager.h
index a5676cf3af68763dd26aeb021ebe7962d54a96b9..1d6aede8e6d0c3a2c614bf8b6d86d2ff7f6b4a91 100644
--- a/Source/RWTHVRQuickStart/Public/PointOfInterestManager.h
+++ b/Source/RWTHVRQuickStart/Public/PointOfInterestManager.h
@@ -42,6 +42,21 @@ public:
 	UFUNCTION(BlueprintCallable, Category="Point Of Interest Manager")
 	int GetPointOfInterestCount();
 
+	/**
+	 * Whether the camera should progress a constant distance between ticks (true) or a variable distance based on frametimes (false).
+	 * This should be set to true if you expect long/inconsistent frame times or for e.g. PSO gathering.
+	 */
+	UPROPERTY(EditAnywhere, Category="Point Of Interest Manager")
+	bool MakeCameraRideProgressionConstantBetweenTicks = true;
+
+	/**
+	 * Only relevant when MakeCameraRideProgressionConstantBetweenTicks = true.
+	 * The conversion rate of how many ticks the camera should update to equal the distance traveled during 1 second.
+	 */
+	UPROPERTY(EditAnywhere, Category="Point Of Interest Manager",
+		meta = (EditCondition = "MakeCameraRideProgressionConstantBetweenTicks"))
+	int CameraRideSecondsToUpdates = 60;
+
 protected:
 	UPROPERTY(EditAnywhere)
 	TArray<APointOfInterest*> POIs;
@@ -57,8 +72,9 @@ private:
 
 	USplineComponent* SplineComponent;
 
-	UPROPERTY(EditAnywhere,  meta=(UIMin = 0.0, UIMax = 500))
+	UPROPERTY(EditAnywhere, meta=(UIMin = 0.0, UIMax = 500))
 	float CameraSpeed = 100;
 	bool IsRidingCamera;
 	float CameraRideStart, CameraRideEnd;
+	int DurationInUpdates, CurrentUpdate;
 };