Download

Follow behind an actor at set distance along the exact same path as followed actor?

Imagine basically snake.

It’s body follows behind the snake head in exactly the same path. When the head accelerates, so do the bodies and when it slows, so do its bodies.

I was thinking of using USplineComponents but I would need to keep adding new points to it but I couldn’t figure out how I would deal with deleting old points I no longer need in there.

I could also keep x amount of USplineComponents and switch between them, clearing them as the last body stops using the USplineComponent. Not sure how efficient this would be either :(.

Anyone know if there is a better way to go about this? Normally in 2D snake this isn’t a problem as everything is split into large squares and the bodies move to previous square of the head.

However I am trying to do this in a 3d space where while theoretically it’s just smaller squares, I am not sure how to apply this here.

At the moment, I am keeping TArray<FVector> and just following that by passing in old position of snake head everytime snake head moves. However this makes head separate from the body if the snake head changes speed. Ideally I would be keeping track of each distance between each FVector but wanted to see if there was a solution already via some obscure component I do not know about.

Thanks!

Alright, I actually found the way to go about this and it’s quite simple. I couldn’t find a pre-existing solution but, it’s not too difficult to implement.

Not sure if this is efficient or not, but works good enough. If anyone finds a better solution hopefully you can share.

I basically created a FollowThroughComponent (which basically can be just a class to be honest).
It contains:



TArray<TPair<FVector, float>> PointsToGo;
int MaxSize;
int NextIndexPosition;


Then in the main actor that followers will follow, it will basically call every tick when it moves.



FollowThroughComponent.Add(CurrentLocation, DistanceMoved);
Followers.Move(DistanceMoved);


When Followers are initialized or started, it starts with the NextIndexPosition but waits until wanted distance is achieved. Then it starts going through the PointsToGo reducing distance as required.

The followers will never collide as it will always move the same amount as the main lead. This is also limited to MaxSize array so I don’t have to worry about any memory growing out of control as game goes on. This is done by using NextIndexPosition and if it passes MaxSize, it returns to 0 and overwrites starting from beginning again.

Full code for my follower code is:



        float RemainingDistance = Distance;
        FVector ControlPoint = GetActorLocation();
        FVector FinalLocation = GetActorLocation();
        FRotator FinalRotation = GetActorRotation();

        // Limit our loops.
        for (int i = 0; i < 10; i++) {
            TPair<FVector, float> PosDis = FollowsComponent->Get(FollowThroughIndex);
            float TravelableAmount = PosDis.Value * RemainderDistancePortion;


            // We can reach it with this jump.
            if (RemainingDistance <= TravelableAmount) {
                // Previous * d + Now + remainder * d = d
                // remainder = (d - prev*d - now)/d
                // remainder = 1 - (1- prev_remainder) - now/d
                // remainder = prev_remainder - now/d
                RemainderDistancePortion = RemainderDistancePortion - RemainingDistance / PosDis.Value;

                // Get the amount of move change by remaining portion.
                FVector Delta = (PosDis.Key - ControlPoint) * (1 - RemainderDistancePortion);

                // Get final location.
                FinalLocation = ControlPoint + Delta;
                FinalRotation = Delta.Rotation();
                break;
            }
            // We cannot reach it with this jump.
            else {
                // "Travel" the amount first.
                RemainingDistance -= TravelableAmount;

                // Now for next jump, remaining distance is 1.
                RemainderDistancePortion = 1;

                // Move follow through index.
                FollowThroughIndex = FollowsComponent->GetNextIndexFor(FollowThroughIndex);

                // Set new control point.
                ControlPoint = PosDis.Key;
            }
        }

        SetActorLocationAndRotation(FinalLocation, FinalRotation);