Fastcast droplet/puddle system not functioning when optimized

hi there,
ive been working on a droplet/puddle system that uses fastcast in order to project and predict droplet physics.

however, i recently encountered an error when i tried to optimize the script by not making a new caster per batch of droplets created, which i tried to do by placing the line outside of the function. this however created several puddles per droplet hit, and ive had trouble solving this since then.

my code is down below with annotated lines showing where the current caster creation is and where i want it to be. any help would be appreciated!

local RS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TweenService")
local DS = game:GetService("Debris")
local runS = game:GetService("RunService")

local modules = RS:WaitForChild("modules")
local fastcast_module = require(modules:WaitForChild("fastcast_module"))

local projectiles = workspace:WaitForChild("projectiles")

--local droplet_caster = fastcast_module.new() -- when i put the droplet caster creation line here to avoid memory usage, puddles spawn in one place en masse where a single droplet hits (droplets and fastcast dont seem to be the problem) my game is eventually lagged to unplayability

local puddle_template = script:WaitForChild("puddle")
local droplet_template = script:WaitForChild("droplet")

local behavior = fastcast_module.newBehavior()
local parameters =  RaycastParams.new()

local droplets_module = {}
	
	function droplets_module.create_droplets(
		amount,
		filter_descendant_instances,
		droplet_origin,
		droplet_direction_min,
		droplet_direction_max,
		random_droplet_direction,
		droplet_velocity_min,
		droplet_velocity_max,
		droplet_size, 
		droplet_acceleration,
		puddle_size_min,
		puddle_size_max,
		puddle_size_tween_time_min,
		puddle_size_tween_time_max,
		puddle_lifetime_min,
		puddle_lifetime_max,
		puddle_fade_out
	)
		
		local i = 0
		
		local droplet_acceleration = droplet_acceleration
		local droplet_velocity = math.random(droplet_velocity_min,droplet_velocity_max)

		local droplet_caster = fastcast_module.new() -- this is the place where the caster is right now, but i want it to  be outside of the function to avoid unecessary memory usage
		
		parameters.FilterType = Enum.RaycastFilterType.Exclude
		parameters.FilterDescendantsInstances = {filter_descendant_instances}

		behavior.RaycastParams = parameters
		behavior.Acceleration = droplet_acceleration
		behavior.AutoIgnoreContainer = true
		behavior.CosmeticBulletTemplate = droplet_template
		behavior.CosmeticBulletContainer = projectiles
		
		while i < amount do
			if random_droplet_direction then
				droplet_caster:Fire(droplet_origin,Vector3.new(math.random(-360,360),math.random(-360,360),math.random(-360,360)),droplet_velocity,behavior)
			else
				local droplet_direction = Vector3.new(
					math.random(droplet_direction_min.X,droplet_direction_max.X),
					math.random(droplet_direction_min.Y,droplet_direction_max.Y),
					math.random(droplet_direction_min.Z,droplet_direction_max.Z)
				)
				
				droplet_caster:Fire(droplet_origin,droplet_direction,droplet_velocity,behavior)
			end

			
			i += 1
			
			--print(i.." of "..amount.." has been reached")
		end
		

		
		droplet_caster.LengthChanged:Connect(function(active_cast,last_position,ray_direction,displacement,segment_velocity,cosmetic_droplet_object)

			local new_cframe = CFrame.new()
			local new_position = last_position + (ray_direction * displacement)

			new_cframe *= CFrame.lookAt(last_position,new_position)

			local cframe_tween_info = TweenInfo.new(0.01,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut)
			local cframe_tween = TS:Create(cosmetic_droplet_object,cframe_tween_info,{CFrame = new_cframe})
			cframe_tween:Play()

			--cosmetic_droplet_object.CFrame = new_cframe

		end)

		droplet_caster.RayHit:Connect(function(active_cast,raycast_result,segment_velocity,cosmetic_droplet_object)

			cosmetic_droplet_object:Destroy()
				
			local puddle = puddle_template:Clone()
			puddle.Anchored = false
		
			local puddle_weld = Instance.new("WeldConstraint",puddle)
			puddle_weld.Part0 = puddle
			
			if raycast_result.Instance ~= nil then
				puddle.CFrame = CFrame.new(raycast_result.Position,raycast_result.Position + raycast_result.Normal)
			end
			
			puddle_weld.Part1 = raycast_result.Instance
			
			puddle.Size = Vector3.new(
				puddle_size_min.X/2,
				puddle_size_min.Y/2,
				puddle_size_min.Z/2
			)
			
			local puddle_size_x = math.random(puddle_size_min.X*1000,puddle_size_max.X*1000)/1000
			local puddle_size_y = math.random(puddle_size_min.Y*1000,puddle_size_max.Y*1000)/1000
			local puddle_size_z = math.random(puddle_size_min.Z*1000,puddle_size_max.Z*1000)/1000
			
			local puddle_size = Vector3.new(
				puddle_size_x,
				puddle_size_x,
				puddle_size_z
			)
			
			local puddle_size_tween = TS:Create(
				puddle,
				TweenInfo.new(
					math.random(puddle_size_tween_time_min*1000,puddle_size_tween_time_max*1000)/1000,
					Enum.EasingStyle.Quad,
					Enum.EasingDirection.Out
				),
				{Size = puddle_size}
			)
			
			puddle_size_tween:Play()
			
			puddle.Parent = workspace
			
			local puddle_lifetime = math.random(puddle_lifetime_min,puddle_lifetime_max)
			
			DS:AddItem(puddle,puddle_lifetime)
			
			if puddle_fade_out then
				local puddle_fade_out_tween = TS:Create(
					puddle,
					TweenInfo.new(
						puddle_lifetime,
						Enum.EasingStyle.Linear,
						Enum.EasingDirection.Out
					),
					{Transparency = 1}
				)
				puddle_fade_out_tween:Play()
			end
			
		end)
		
	end

return droplets_module