<style>.lazy{display:none}</style> Skip to main content
Category

Development

Unreal Engine C++ Fundamentals – Moving Static Meshes along a Spline Component

By Props, Tutorial, Unreal No Comments

Hey guys,

Today we are going to take a look how to use Spline Components and modify their various properties to allow us to specify custom materials as well as determine how meshes are attached to the spline.

The project files for this video & article can be found on our GitHub page.

Looking at our previous tutorial we know that splines are not terribly hard to work with but there is a bit of magic to having something move along a spline.

The key ingredient in this is the FTimeline. This allows us to keep track of an execution of values across a specific timeframe.

The FTimeline combined with a UCurveFloat gives us all that flexibility. So let’s look at the code to see how this all breaks down.

FTimeline MovementTimeline;

FOnTimelineFloat ProgressFunction; ProgressFunction.BindUFunction(this, TEXT("ProcessMovementTimeline")); MovementTimeline.AddInterpFloat(MovementCurve, ProgressFunction); FOnTimelineEvent OnTimelineFinishedFunction; OnTimelineFinishedFunction.BindUFunction(this, TEXT("OnEndMovementTimeline")); MovementTimeline.SetTimelineFinishedFunc(OnTimelineFinishedFunction); MovementTimeline.SetTimelineLengthMode(TL_LastKeyFrame); if(bAutoActivate) { MovementTimeline.PlayFromStart(); }

Looking over the code we can see that as part of the FTimeline definition we are specifying a function that will be executed during the runtime of the timeline.

UFUNCTION()
void ProcessMovementTimeline(float Value);

As well as a function at will be executed at the end of our timeline.

UFUNCTION()
void OnEndMovementTimeline();

Additionally we need to ensure that our timeline ticks as part of our object. For this we can examine the Tick method.

// Called every frame
void AMovingSplineActor::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);

  if(MovementTimeline.IsPlaying())
  {
    MovementTimeline.TickTimeline(DeltaTime);	
  }
}

Now let’s take a look at the magic around moving the mesh across the spline. This all happens within our ProcessMovementTimeline method.

void AMovingSplineActor::ProcessMovementTimeline(float Value)
{
  const float SplineLength = SplineComponent->GetSplineLength();

  const FVector CurrentSplineLocation = SplineComponent->GetLocationAtDistanceAlongSpline(Value * SplineLength, ESplineCoordinateSpace::World);
  FRotator CurrentSplineRotation = SplineComponent->GetRotationAtDistanceAlongSpline(Value * SplineLength, ESplineCoordinateSpace::World);

  CurrentSplineRotation.Pitch = 0.f;
  MeshComponent->SetWorldLocationAndRotation(CurrentSplineLocation, CurrentSplineRotation);
}

As you can see the logic is not that scary. We are simply taking the delta time by the lenght of the spline and retrieving that points location and rotation.

This is then applied to our mesh and we prevent the pitch from being corrected so our elevator / platform does not tip as it’s traversing along the spline.

Lastly let’s take a look at the function OnEndMovementTimeline() which is called at the .. you guessed it … end of our timeline.

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Spline", meta=(EditCondition = "!bRestartOnEndTimeline"))
bool bReverseOnEndTimeline;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Spline", meta=(EditCondition = "!bReverseOnEndTimeline"))
bool bRestartOnEndTimeline;
void AMovingSplineActor::OnEndMovementTimeline()
{
  if(bReverseOnEndTimeline)
  {
    MovementTimeline.Reverse();
  }
  else if(bRestartOnEndTimeline)
  {
    MovementTimeline.PlayFromStart();
  }
}

This function is a great spot to put in logic for things like restarting the movement or reversing the movement by injecting some simple properties into our new object.

For further reading about these topics take a look at the following links: