Why is my script cloning more things than it's supposed to?

  1. What do you want to achieve? Keep it simple and clear!

I have a medkit tool and I made it clone the tool model to simulate “dropping” said medkit.

  1. What is the issue? Include screenshots / videos if possible!

Only after the first use it works as intended, but every use after that increases the number of clones produced by 1.

(Use one, 1 clone | Use two, 2 clones | Use three, 3 clones | etc.)

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I’ve tried searching it up but I don’t believe any helped me with this specifically, although I could be wrong.

Yeah, I know that this script could be improved.

remote.OnServerEvent:Connect(function(plr, func)
	local char = plr.Character or plr.CharacterAdded:Wait()
	
	if func == "lid" then
		local lid = handle:WaitForChild("Lid")
		if lid then
			local lidClone = lid:Clone()
			lidClone.Parent = game.Workspace
			lidClone.CFrame = lid.CFrame
			editProperties(lidClone, 0, true, true)
			editProperties(lid, 1, false, true)
			
			for i, v in pairs(lidClone:GetDescendants()) do
				if v:IsA("CFrameValue") then
					v:Destroy()
				elseif v:IsA("Weld") then
					v:Destroy()
				end
			end
			
			wait()
			
			lidClone.Velocity = Vector3.new(25, 32.5, 15)
			debris:AddItem(lidClone, 5)
		end
	elseif func == "syringe" then
		local syringe = serverStorage:WaitForChild("Player"):FindFirstChild("Syringe")
		if syringe then
			local syringeClone = syringe:Clone()
			syringeClone.Parent = game.Workspace
			
			local weld = Instance.new("Weld")
			weld.Name = "syringeWeld"
			weld.Part0 = syringeClone
			weld.Part1 = char:WaitForChild("Left Arm")
			weld.C0 = weld.Part0.LeftGripAttachment.CFrame
			weld.C1 = weld.Part1.LeftGripAttachment.CFrame
			weld.Parent = syringeClone
		end
	elseif func == "heal" then
		local human = char:WaitForChild("Humanoid")
		human.Health = human.Health + healAmount.Value
	elseif func == "drop" then
		local containerClone = handle:Clone()
		containerClone.Parent = game.Workspace
		containerClone:FindFirstChild("Lid"):Destroy()
		editProperties(handle, 1, false, false)
		editProperties(containerClone, 0, true, false)

		local syringeClone = game.Workspace:WaitForChild("Syringe")
		if syringeClone then
			syringeClone:FindFirstChild("syringeWeld"):Destroy()
			editProperties(syringeClone, 0, true, false)
			debris:AddItem(syringeClone, 7.5)
		end
		
		debris:AddItem(containerClone, 7.5)
	elseif func == "reset" then
		editProperties(handle, 0, false, false)
	end
end)

I can provide the full script, although I think this is the most important part.
As for the remote event, it fires to the server whenever the medkit animation reaches a certain keyframe.

that could happen if you were to make a new remote listener each time you clicked a button, so since youre making a new remote every time you click, it increases each time.

1 Like

This is likely the problem but it is hard to figure out without the code that actually runs the event. @zootedtohell can you provide the client code?

for example

for i=1,10 do
     remote.OnServerEvent:Connect(function()
     print("hi")
     end)
end

if you were to fire this remote once, it will print 10 times as there are 10 listeners to the event

1 Like

I am kind of confused but I think I get the idea. How do I fix it then?

Yeah, of course!

Client
local players = game:GetService("Players")
local plr = players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local human = char:WaitForChild("Humanoid")

local tool = script.Parent
local objects = tool:WaitForChild("Objects")
local remote = objects:FindFirstChild("medkitRemote")
local anim = human:LoadAnimation(objects:FindFirstChild("Healing", 10))

local healAmount = objects:FindFirstChild("healAmount")
local lastHealed = os.time()
local debounce = true

tool.Activated:Connect(function()
	if debounce == true then
		debounce = false
		anim:Play()
		
		anim.KeyframeReached:Connect(function(keyframeName)
			if keyframeName == "Lid" then
				remote:FireServer("lid")
			elseif keyframeName == "Syringe" then
				remote:FireServer("syringe")
			elseif keyframeName == "Heal" then
				remote:FireServer("heal")
			elseif keyframeName == "Drop" then
				remote:FireServer("drop")
			end
		end)
		
		wait(10)
		remote:FireServer("reset")
		debounce = true
	end
end)
Server
local serverStorage = game:GetService("ServerStorage")
local debris = game:GetService("Debris")

local tool = script.Parent
local handle = tool:WaitForChild("Handle")
local objects = tool:WaitForChild("Objects")
local remote = objects:FindFirstChild("medkitRemote")
local sound = objects:FindFirstChild("Heal")

local healAmount = objects:FindFirstChild("healAmount")
local lastHealed = os.time()

local anim = Instance.new("Animation")
anim.Name = "Healing"
anim.Parent = objects
anim.AnimationId = "rbxassetid://7226557052"

local function editProperties(part, transparency, collision, editoriginal)
	if editoriginal == true then
		part.Transparency = transparency
		part.CanCollide = collision
	end
	
	for i, v in pairs(part:GetDescendants()) do
		if v:IsA("BasePart") then
			v.Transparency = transparency
			v.CanCollide = collision
		elseif v:IsA("Decal") then
			v.Transparency = transparency
		end
	end
end

local function checkProperty(object, prop)
	local t = object[prop]
end

remote.OnServerEvent:Connect(function(plr, func)
	local char = plr.Character or plr.CharacterAdded:Wait()
	
	if func == "lid" then
		local lid = handle:WaitForChild("Lid")
		if lid then
			local lidClone = lid:Clone()
			lidClone.Parent = game.Workspace
			lidClone.CFrame = lid.CFrame
			editProperties(lidClone, 0, true, true)
			editProperties(lid, 1, false, true)
			
			for i, v in pairs(lidClone:GetDescendants()) do
				if v:IsA("CFrameValue") then
					v:Destroy()
				elseif v:IsA("Weld") then
					v:Destroy()
				end
			end
			
			wait()
			
			lidClone.Velocity = Vector3.new(25, 32.5, 15)
			debris:AddItem(lidClone, 5)
		end
	elseif func == "syringe" then
		local syringe = serverStorage:WaitForChild("Player"):FindFirstChild("Syringe")
		if syringe then
			local syringeClone = syringe:Clone()
			syringeClone.Parent = game.Workspace
			
			local weld = Instance.new("Weld")
			weld.Name = "syringeWeld"
			weld.Part0 = syringeClone
			weld.Part1 = char:WaitForChild("Left Arm")
			weld.C0 = weld.Part0.LeftGripAttachment.CFrame
			weld.C1 = weld.Part1.LeftGripAttachment.CFrame
			weld.Parent = syringeClone
		end
	elseif func == "heal" then
		local human = char:WaitForChild("Humanoid")
		human.Health = human.Health + healAmount.Value
	elseif func == "drop" then
		local containerClone = handle:Clone()
		containerClone.Parent = game.Workspace
		containerClone:FindFirstChild("Lid"):Destroy()
		editProperties(handle, 1, false, false)
		editProperties(containerClone, 0, true, false)

		local syringeClone = game.Workspace:WaitForChild("Syringe")
		if syringeClone then
			syringeClone:FindFirstChild("syringeWeld"):Destroy()
			editProperties(syringeClone, 0, true, false)
			debris:AddItem(syringeClone, 7.5)
		end
		
		debris:AddItem(containerClone, 7.5)
	elseif func == "reset" then
		editProperties(handle, 0, false, false)
	end
end)

Found it, you seem to be connecting to “KeyframeReached” multiple times. You should store the connection in a variable and disconnect it when you don’t need it anymore!

Connect() returns a “connection” that you can disconnect later on.

--(client script)
local connection = anim.KeyframeReached:Connect(function(keyframeName)
	if keyframeName == "Lid" then
		remote:FireServer("lid")
	elseif keyframeName == "Syringe" then
		remote:FireServer("syringe")
	elseif keyframeName == "Heal" then
		remote:FireServer("heal")
	elseif keyframeName == "Drop" then
		remote:FireServer("drop")
	end
end)

--(we dont need it anymore)
connection:Disconnect()

You may want to read this dev hub article, it has alot of information that will help you!

2 Likes

Thank you! It worked. :grin:
I’ve been confused on when I should be disconnecting events so this helps to know.

1 Like

Happy to help, glad i could do something! :+1:

1 Like