Skip to content

Instantly share code, notes, and snippets.

@braustin20
Created May 30, 2018 17:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save braustin20/220145d54aa1f419e719cf607a637765 to your computer and use it in GitHub Desktop.
Save braustin20/220145d54aa1f419e719cf607a637765 to your computer and use it in GitHub Desktop.
Unreal 4 spline movement script
void ASplineCharacter::MoveRight(float Value)
{
if (GameStateRef == nullptr || GameStateRef->MovementSpline == nullptr)
{
AddMovementInput(FVector(0.f, -1.f, 0.f), Value);
return;
}
//Orient and move player in the direction of the spline
SplineDirection = GameStateRef->MovementSpline->Spline->FindDirectionClosestToWorldLocation(GetActorLocation(), ESplineCoordinateSpace::World);
SplineDirection.Z = 0.0f;
SplineDirection.Normalize();
AddMovementInput(SplineDirection, Value);
SplineStatus = GameStateRef->MovementSpline->ReachedSplineLimit(GetActorLocation() + GetCharacterMovement()->GetPendingInputVector() * 50.0f);
//If we're at the end of the spline and are clamping movement, stop the player. Otherwise, adjust lateral movement.
if (ClampToSpline && SplineStatus != ESplineLocationStatus::SL_OnSpline)
{
//NOTE: Could use a ternary for this but decided a switch was more readable
switch (SplineStatus) {
case ESplineLocationStatus::SL_ReachedBegin :
SplineLocation = GameStateRef->MovementSpline->Spline->GetLocationAtDistanceAlongSpline(GameStateRef->MovementSpline->DistanceAtStart, ESplineCoordinateSpace::World);
break;
case ESplineLocationStatus::SL_ReachedEnd :
SplineLocation = GameStateRef->MovementSpline->Spline->GetLocationAtDistanceAlongSpline(GameStateRef->MovementSpline->DistanceAtEnd, ESplineCoordinateSpace::World);
break;
}
GetMovementComponent()->ConsumeInputVector();
SplineLocation.Z = GetActorLocation().Z;
}
else
{
//Find the nearest point to player on the spline
SplineLocation = GameStateRef->MovementSpline->Spline->FindLocationClosestToWorldLocation(GetActorLocation(), ESplineCoordinateSpace::World);
if (CameraActorRef != nullptr)
CameraActorRef->TargetLocation = FVector(GetActorLocation().X, GetActorLocation().Y, SplineLocation.Z);
SplineLocation.Z = GetActorLocation().Z;
//Get the vector from the player's location to the nearest point on the spline
FVector SplineLocationVector = (GetActorLocation() - SplineLocation);
SplineLocationVector.Z = GetActorLocation().Z;
//Calculate the tangent of the spline at the nearest point and determine the distance to the player
FVector splineTangent = FVector::CrossProduct(SplineDirection, FVector::UpVector);
DistanceToSpline = FVector::DotProduct(SplineLocationVector, splineTangent);
//Find the spline point directly to the side of the player
//This is necessary to prevent forward/backward movement along the spline unless applied by the CharacterMovement component
SplineLocation = -DistanceToSpline * splineTangent.GetSafeNormal() + GetActorLocation();
}
//Smoothly move the player onto the spline
SplineLocation = FMath::VInterpTo(GetActorLocation(), SplineLocation, GetWorld()->GetDeltaSeconds(), SplineLerpSpeed);
SetActorLocation(SplineLocation, true, nullptr,ETeleportType::TeleportPhysics);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment