How to make boids be a bit more stable?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to make boids that look like this video.

  2. What is the issue? Include screenshots / videos if possible!
    Although the code works, the boids change direction a lot, and quite abruptly, resulting in stuff like this:

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried lerping to see if that would stabilise it, but it’s not working.

Here is the code for the boids that matters:

function  Boid.__index:CalculateDirection(): Vector3?
    local AverageHeading = ZERO_VECTOR
    local AveragePosition = ZERO_VECTOR
    local SeperationHeading = ZERO_VECTOR
    local NumBoids = 0
    local AvoidBoids = 0
    for Id, OtherBoid in ipairs(BoidArray) do
        if OtherBoid.Id == self.Id then
            continue
        end
        local Offset = OtherBoid.Position - self.Position
        local Distance = Offset.Magnitude

        if Distance > self.Range then
            continue
        end
        if GetAngleBetweenVectors(self.Position, OtherBoid.Position) > self.ViewAngle then
            continue
        end
        AverageHeading += OtherBoid.Direction
        AveragePosition += OtherBoid.Position
        if Distance < AVOID_RADIUS then
            SeperationHeading -= Offset / Distance
            AvoidBoids += 1
        end
        NumBoids += 1
    end
    if NumBoids < 1 then
        return
    end
    
    AverageHeading /= NumBoids
    AverageHeading *= ALIGN_WEIGHT
    AveragePosition = AveragePosition / NumBoids - self.Position
    AveragePosition *= COHESIVE_WEIGHT
    -- Dividing by 0 results in nan values, which caused me way too much headache :/ 
    if AvoidBoids > 0 then
        SeperationHeading /= AvoidBoids
        SeperationHeading *= SEPERATION_WEIGHT
    else 
        return ClampVector(AverageHeading + AveragePosition, MAX_VELOCITY)
    end
    return ClampVector(AverageHeading + AveragePosition + SeperationHeading, MAX_VELOCITY)
end
function Boid.__index:Update(dt: NumberValue)
    local NewHeading = self:CalculateDirection()
    if NewHeading then
        self.Direction += NewHeading * dt
        self.Direction = self.Direction.Unit
    end
    self.Position += self.Direction * dt
    --VectorVisualizer.UpdateVector(self.VectorVisualizer, self.Direction, self.Position)
end

I feel as if that behavior is supposed to happen because in the video you only ever see the Boids moving. Have you tried making them follow a part?

If it’s still an issue, then I recommend implementing a creates a variable of the boid’s starting position and tries to keep it in that general position if it hasn’t been programmed to follow a part.