If we now look at the Tick method in UEBoidManager.cpp, we can see the implementation.

void ABoidManager::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	int i = 0;

	for (BoidData& data : myBoidData)
	{
		FVector meanPos(0.f);
		FVector meanVel(0.f);
		FVector avoidance(0.f);

		int numInCohesionRange = 0;
		int numInAlignRange = 0;
		int j = 0;

		for (const BoidData& innerBoid : myBoidData)
		{
			if (i != j)
			{
				float dist2 = FVector::DistSquared(data.myPosition, innerBoid.myPosition);

				// Calculate our values for Cohesion, Avoidance, and Alignment

				// For Cohesion, we need the mean position of nearby boids
				if (dist2 < myParameters.myCohesionRange2)
				{
					meanPos += innerBoid.myPosition;
					numInCohesionRange++;
				}

				// For avoidance, we add a vector pointing away from any nearby boids in range
				if (dist2 < (myParameters.myAvoidRange2))
				{
					avoidance +=  data.myPosition - innerBoid.myPosition;
				}

				// For alignment, we need the mean velocity of nearby boids
				if (dist2 < (myParameters.myAlignRange2))
				{
					meanVel += innerBoid.myVelocity;
				}
				
			}
			++j;
		}

		// Coherence is a vector pointing from current pos towards the mean position of other boids within range
		if(numInCohesionRange)
			meanPos /= numInCohesionRange;

		FVector coherence = (meanPos - data.myPosition) * myParameters.myCohesionWeight;

		if (numInAlignRange)
			meanVel /= numInAlignRange;

		FVector alignment = meanVel * myParameters.myAlignWeight;

		// Calculate bounds vector, push us back inside the volume if we leave it
		FVector bounds(0.f);

		if (data.myPosition.X < myAABBMin.X) {
			bounds.X = myParameters.myAvoidBoundsWeight;
		} else if (data.myPosition.X > myAABBMax.X) {
			bounds.X = -myParameters.myAvoidBoundsWeight;
		}

		if (data.myPosition.Y < myAABBMin.Y) {
			bounds.Y = myParameters.myAvoidBoundsWeight;
		} else if (data.myPosition.Y > myAABBMax.Y) {
			bounds.Y = -myParameters.myAvoidBoundsWeight;
		}

		if (data.myPosition.Z < myAABBMin.Z) {
			bounds.Z = myParameters.myAvoidBoundsWeight;
		} else if (data.myPosition.Z > myAABBMax.Z) {
			bounds.Z = -myParameters.myAvoidBoundsWeight;
		}

		bounds *= myParameters.myAvoidBoundsWeight;

		// Add up the component vectors, and Lerp towards to the new velocity to keep things smooth.
		data.myVelocity = FMath::Lerp(data.myVelocity, (data.myVelocity + (coherence + avoidance + alignment + bounds)).GetClampedToMaxSize(myParameters.myVelocityMax), DeltaSeconds * 10.f);
		data.myPosition += data.myVelocity * DeltaSeconds;

		// Calculate instance transform. Probably a more efficient way to calculate rotation here?
		FTransform tx; 
		myMeshComponent->GetInstanceTransform(i, tx);
		FQuat lookAtRotator = FRotationMatrix::MakeFromX(data.myVelocity).ToQuat();
		tx.SetRotation(lookAtRotator);
		tx.SetLocation(data.myPosition);

		// Apply the new transform
		myMeshComponent->UpdateInstanceTransform(i, tx, false, i < myBoidData.Num() - 1, true);

		++i;
	}
}