Why does this gun script keep lagging my game?

I made a simple gun script, but when I go to activate the tool, it lags the entire game. If tried to remove the connection to see if that would change anything, but it didn’t. I don’t know what is happening and I thought I should ask about it.

local debris = game:GetService("Debris")
local players = game:GetService("Players")
local tool = script.Parent
local handle = tool:WaitForChild("Handle")
local RifleShoot = tool:WaitForChild("RifleShoot")
local debounce = false
local damage = 20
local player
local character
local humanoid
local getmouse = tool:WaitForChild("GetMouse")
local gunIdle = tool:WaitForChild("GunIdle")
local fireSound = handle:WaitForChild("FireSound")


local idle

tool.Equipped:Connect(function()
	character = tool.Parent
	player = players:GetPlayerFromCharacter(character)
	humanoid = character:WaitForChild("Humanoid")
	idle = humanoid:LoadAnimation(gunIdle)
	idle:Play()
end)

tool.Unequipped:Connect(function()
	if idle then
		idle:Stop()
		idle = nil
	end
	character = nil
	player = nil 
	humanoid = nil
end)

tool.Activated:Connect(function()
	if debounce == false then
		debounce = true
		local connection
		local bullet = Instance.new("Part",workspace)
		bullet.Name = "Bullet"
		bullet.Size = Vector3.new(0.225, 0.126, 2)
		bullet.BrickColor = BrickColor.new("New Yeller")
		bullet.Material = "Neon"
		
		local sound = fireSound:clone()
		sound.Parent = handle
		sound:Play()
		debris:AddItem(sound,1)
		
		local mouse = tool.GetMouse:InvokeClient(player)
		print(mouse)
		if mouse then
			local bv = Instance.new("BodyVelocity",bullet)
			bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
			bv.Velocity = (mouse.Position - character.HumanoidRootPart.Position).Unit * 125

			connection = bullet.Touched:Connect(function(hit)
				if not hit.Parent:FindFirstChild("ForceField") then
					if hit.Parent:FindFirstChild("Humanoid") then
						if hit.Parent.Name ~= character.Name then
							if hit.Parent.Humanoid.Health > 0 then
								bullet:Destroy()
								hit.Parent.Humanoid.Health = hit.Parent.Humanoid.Health - damage
								if connection then
									connection:Disconnect()
								end
							end
						end
					end
				end
			end)
		end
		
		wait(1.5)
		
		debounce = false
		if connection then
			connection:Disconnect()
		end
	end
end)

You’re only destroying the projectile if it hits something, try destroying it regardless of whether or not it hits another player.

try not to use invoke client?
1: It is unstable
2: makes exploiting easier

Could be the fact there’s no denounce in the touched function hence it creates many in a short span of time when being in contact with something

I see a couple of things that I would change:

  • InvokeClient is highly unrecommended in this case for 2 reasons: Security and Performance
  1. Security because InvokeClient will mean that the client send anything back and also could yield the server
  2. Performance because it is possible to use a RemoteEvent instead of a RemoteFunction. RemoteFunctions sends data both ways whereas the RemoteEvent sends data 1 way.
  • You would probably want to destroy the bullet regardless of what it hit. In the case that is hits your own character use Raycasting instead as it offers much more precision.

View the docs: Bindable Events and Functions | Roblox Creator Documentation for more info.

  • Recommended to not use the parent argument with Instance.new()
  • Animation Tracks don’t unload

In other words if you Load an animation everytime the player equips a gun the Animation will stay loaded to the character untill the Humanoid dies.

Invoke client was only used to get the mouse of the player. This is a server script…

Yes. That is what you shouldn’t be doing.

Instead have the local script detect when the tool is used and activated and send RemoteEvents to the server to fire the gun.

I recommend you read this article if you haven’t already.

Its very complicated in making smooth working gun. The best thing you can do is managing the functions that should be only on client, server, all clients.

I think you should try these out:

  1. All tool functions should be in local script.
    (Equipped, Unequipped, Activated, …etc)

  2. Try to create raycast for hit ditection
    (Raycast on client-side)

  3. Run a sanity check when player hit.

  4. You can create projectile visual by firing a remote event to all clients.

Im not fully professional on this thing, if you find these ideas are wrong please correct me.