How to update the position of the bullets?

I’m using a piece of code similar to fast cast, and I was wondering if there was anyway to update the position of all the projectiles individually?

A different way of wording this being, how to manage multiple parts and their positions in a function with only one variable?

tldr version

function projectile.new()
	function newprojectilecast()
-- math
		local connection = runservice.Heartbeat:Connect(function(DeltaTime)
--math
			currentPos = projectilePosition
				
				if self.Visalize and newobjectis == nil then
					local newobjectis = Instance.new("Part")
--information
				end
				newobjectis.position = currentPos	
		end
-- when the projectile hits something, it then does
		newobjectis = nil
		connection:Disconnect()
end
end

full version

local Projectile = {}


function Projectile.new(Gravity, BlackList, Wind, DespawnTime, Visalize)
	local newprojectile = {}
	newprojectile.Gravity = Gravity
	newprojectile.BlackList = BlackList
	newprojectile.Wind = Wind
	newprojectile.DespawnTime = DespawnTime
	newprojectile.Visalize = Visalize
	newprojectile.Params = RaycastParams.new()
	
	newprojectile.Params.FilterType = Enum.RaycastFilterType.Exclude
	newprojectile.Params.FilterDescendantsInstances = BlackList
	visual.visiual()
	function newprojectile:Cast(start, dest, force)
		
		local VFORCE= (dest - start).Unit * force * 20
		
		local a = Vector3.new(self.Wind.X, self.Wind.Y - self.Gravity * 9.8, self.Wind.Z) * 20 
		
		local t = 0
		local currentPos = start
		local rayResult = nil
		local Found = false
		local connection = runservice.Heartbeat:Connect(function(DeltaTime)
			if not Found then
			t = t + DeltaTime
			
			local projectilePosition = Vector3.new(
				start.X + VFORCE.X * t + 0.5 * a.X * t * t,
				start.Y + VFORCE.Y * t + 0.5 * a.Y * t * t,
				 start.Z + VFORCE.Z * t + 0.5 * a.Z * t * t
			)
			
			rayCastResulT = workspace:Raycast(currentPos, projectilePosition - currentPos, self.Params)
			
			currentPos = projectilePosition
			--print(DeltaTime, self.Gravity)
				
				if self.Visalize and newobjectis == nil then
									local newobjectis = Instance.new("Part")
		newobjectis.CanQuery = false
		newobjectis.Parent = workspace
		newobjectis.Anchored = true

		newobjectis.CanCollide = false
		newobjectis.Transparency = 0.5
		newobjectis.Color = Color3.fromRGB(255, 0, 0)
		newobjectis.Size = Vector3.new(1,1,1)
		newobjectis.Parent = workspace
		debris:AddItem(newobjectis, 4)
				end
				newobjectis.position = currentPos
			
			if rayCastResulT or t > self.DespawnTime  then
				Found = true
				print("shouldbedealtwith")
			end
			end
			
		end)

		while not Found do 
			wait()
		end
		
		connection:Disconnect()
		
		if rayCastResulT then 
			print("found")
		else
			print("not found")
		end
	end
	return newprojectile
end

Now, while I could just do the math again and make a visualisation function from a task.spawn, I was wondering if there was any other way to make this work? I was wondering if there was any way for this to not have to do the math again, and simply update the positions of all the projectiles by themselves.

here’s what the current problem, where the script can only have one piece and block/visual at the same time