DEV Community

Maciej Sawicki
Maciej Sawicki

Posted on

[Game of Purpose] Day 59 - Following a path either by distance or Spline points

Today I was playing around with supporting 2 ways of following a path.

  • By distance - Given a path it moves to a point every x distance.
  • By points - Given a path it moves to each point the Spline has configured.

https://blueprintue.com/blueprint/zmunmar-/

Image description

And my full path-following code looks like this:

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/SplineComponent.h"
#include "DrawDebugHelpers.h"
#include "SplineFollowerBase.generated.h"

UENUM(BlueprintType)
enum class EFollowingType : uint8
{
    ByDistance UMETA(DisplayName = "By Distance"),
    ByPoints UMETA(DisplayName="By Points")
};

UCLASS(BlueprintType, Blueprintable)
class SKY_PATROL_API USplineFollowerBase : public UActorComponent
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spline")
    USplineComponent* TargetSpline;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spline")
    float DistanceToMove = 200.0f;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spline")
    EFollowingType FollowingType = EFollowingType::ByDistance;

protected:
    UFUNCTION(BlueprintCallable)
    UPARAM(DisplayName="NextTargetDistance") float CalculateNextTargetDistanceBase();

    UFUNCTION(BlueprintCallable)
    UPARAM(DisplayName="NextPointIndex") int CalculateNextPointIndexBase();

private:
    float NextTargetDistance = -1.0f;
    int NextPointIndex = -1;
};
Enter fullscreen mode Exit fullscreen mode
#include "SplineFollowerBase.h"

#include "Utils/MyStringUtils.h"

float USplineFollowerBase::CalculateNextTargetDistanceBase()
{
    check(TargetSpline != nullptr);

    const auto TargetSplineTotalLength = TargetSpline->GetSplineLength();

    // staring the movement
    if (NextTargetDistance < 0.0f)
    {
        NextTargetDistance = 0.0f;
    }
    // looping
    else if (NextTargetDistance >= TargetSplineTotalLength)
    {
        NextTargetDistance = 0.0f;
    }
    else
    {
        NextTargetDistance = FMath::Clamp(NextTargetDistance + DistanceToMove, 0.0f, TargetSplineTotalLength);
    }

    PrintString(FString::Printf(TEXT("NextTargetDistance: %f"), NextTargetDistance));


    return NextTargetDistance;
}

int USplineFollowerBase::CalculateNextPointIndexBase()
{
    check(TargetSpline != nullptr);

    const auto TargetSplineTotalPoints = TargetSpline->GetNumberOfSplinePoints();

    NextPointIndex = (NextPointIndex + 1) % TargetSplineTotalPoints;

    PrintString(FString::Printf(TEXT("NextPointIndex: %d"), NextPointIndex));

    return NextPointIndex;
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)