I’m having some issues getting an actor to move along a spline at a fixed speed.
I’m generating the spline like this:
local InterpCurveVector splinePath;
local InterpCurvePointVector splinePoint;
local Array<vector> flightPathVectors;
//Add the path i want for generate the spline from.
flightPathVectors.AddItem(someVector1);
flightPathVectors.AddItem(someVector2);
flightPathVectors.AddItem(someVector3);
FlightPathSpline = new(self) class'SplineComponent';
foreach flightPathVectors(pathPointLoc, i) {
splinePoint.InVal = i;
splinePoint.OutVal = pathPointLoc;
splinePoint.InterpMode = CIM_CurveAuto;
splinePath.Points.AddItem(splinePoint);
}
FlightPathSpline.SplineInfo = splinePath;
FlightPathSpline.UpdateSplineCurviness();
FlightPathSpline.UpdateSplineReparamTable();
Then in the actors tick method i have this for moving it along the spline at a constant speed:
simulated function Tick(float deltaTime)
{
local float totalSplineLength;
local float distanceToMove;
local vector planeLocation;
// Calculate the total length of the spline
totalSplineLength = FlightPathSpline.GetSplineLength();
// Calculate the distance the plane should have moved in this frame
distanceToMove = Speed * deltaTime;
// Calculate the new distance after moving this frame
CurrentFlightPathDistance += distanceToMove;
// Get the new location of the plane at the updated distance along the spline
planeLocation = FlightPathSpline.GetLocationAtDistanceAlongSpline(CurrentFlightPathDistance);
// Update the planes location
SetLocation(planeLocation);
}
The problem i have is that the actor seems to slow down and speed up at certain points along the spline. Here is a video example of what i mean:
It is usually when moving across the individual points on the spline.
What I do is move my pawns applying acceleration towards the destination point, this being a spline point found with GetLocationAtDistanceAlongSpline(). Reaching them, I find the next destination, until the end.
That is, I don’t place the pawn with a setlocation() directly in GetLocationAtDistanceAlongSpline().
(However, I suspect that GetLocationAtDistanceAlongSpline() is quite slow if you move many pawns at once.)
I’ve found a solution that solves this issue. Although it does require one additional call to GetLocationAtDistanceAlongSpline().
It’s not perfect, but is very close (in terms of runtime visuals anyway).
It essentially creates adjustments based on how inaccurate the results from GetLocationAtDistanceAlongSpline() compared to the expected distance travelled. By comparing the expected distance travelled with the location returned from an initial GetLocationAtDistanceAlongSpline() call, I create a multiplier to apply to the distance for a subsequent call.
function Tick(float deltaTime)
{
local float expectedDistToMove;
local vector planeLocation;
local float speedAdjuster;
// Calculate the distance the plane should have moved in this frame
expectedDistToMove = Speed * deltaTime;
planeLocation = FlightPathSpline.GetLocationAtDistanceAlongSpline(CurrentFlightPathDistance + expectedDistToMove);
//Calculates a multiplier, based on how inaccurate the GetLocationAtDistanceAlongSpline spline curve calc is,
//so we can apply it and avoid the slow-downs/speed-ups we get if we only use one GetLocationAtDistanceAlongSpline().
speedAdjuster = expectedDistToMove / DistBetween(Location, planeLocation);
// Calculate the new distance after moving this frame.
CurrentFlightPathDistance += (speedAdjuster * expectedDistToMove);
// Get the new location of the plane at the updated distance along the spline.
planeLocation = FlightPathSpline.GetLocationAtDistanceAlongSpline(CurrentFlightPathDistance);
// Update the planes location.
SetLocation(planeLocation);
}
My plane now moves at a fixed speed along the spline and still benefits from the smoothing of the curves (rather than moving from point to point).