While loop crashing

I created a gun script and it worked fine, but then I wanted to make it automatic, so I created a loop to detect whether mouse button is pressed. When I try to shoot, Studio freezes and crashes. I am pretty sure that break and wait are placed incorrectly but I can’t figure out a solution.

local repStorage = game:GetService("ReplicatedStorage")
local bullet = repStorage.Bullet
local gun = script.Parent
local uis = game:GetService("UserInputService")
local player = game.Players.LocalPlayer

local damage = 10
local speed = 100
local cooldown = 1

uis.InputBegan:Connect(function(input, gpe)
	local pressed = uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
	while pressed == true and gpe == false do
		local newBullet = bullet:Clone()
		newBullet.Position = gun.Position + gun.CFrame.LookVector * 5
		newBullet.Parent = game.Workspace
		
		newBullet.Velocity = gun.CFrame.LookVector * speed
		local bodyForce = Instance.new("BodyForce")
		bodyForce.Force = Vector3.new(0, newBullet:GetMass() * workspace.Gravity, 0)
		bodyForce.Parent = newBullet
		
		newBullet.Touched:Connect(function(hit)
			local npc = hit.Parent:FindFirstChild("Humanoid")
			if npc and not game.Players:GetPlayerFromCharacter(npc.Parent) then
				npc:TakeDamage(damage)
				newBullet:Destroy()
			end
		end)
		break
	end
	wait(cooldown)
end)
1 Like

Yes, wait(CoolDown) is placed incorrectly… you should remove break and put wait inside the while loop because currently it is outside the loop so it won’t affect it.

Also, you should not use InputBegan as that will only detect when you first hold the mouse, if you want to recheck you should use InputChanged instead.

1 Like

I was just about to mention it!

It still crashes. Does it matter where exactly I put wait() if it’s inside the loop?

No, as long as it is in the loop then I’m sure it is fine. Probably, add a debounce because theres no reason for it to crash…

You can try rearrange some end functions and mess around with them. The reason it crashes is because you havent added a wait. while true do loops at like the speed of light. Always be sure to add a wait in a while true do script before ending it, or simply do while wait(cooldown) do as im pretty sure that would work too.

Add this as a solution if this helps!

Have a good day.

Try adding a wait() before the second last end or you can move the wait(cooldown)
I’ve edited the script, you can try and see if it works

        local repStorage = game:GetService("ReplicatedStorage")
        local bullet = repStorage.Bullet
        local gun = script.Parent
        local uis = game:GetService("UserInputService")
        local player = game.Players.LocalPlayer

        local damage = 10
        local speed = 100
        local cooldown = 1

        uis.InputBegan:Connect(function(input, gpe)
        	local pressed = uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
        	while pressed == true and gpe == false do
        		local newBullet = bullet:Clone()
        		newBullet.Position = gun.Position + gun.CFrame.LookVector * 5
        		newBullet.Parent = game.Workspace
        		
        		newBullet.Velocity = gun.CFrame.LookVector * speed
        		local bodyForce = Instance.new("BodyForce")
        		bodyForce.Force = Vector3.new(0, newBullet:GetMass() * workspace.Gravity, 0)
        		bodyForce.Parent = newBullet
        		
        		newBullet.Touched:Connect(function(hit)
        			local npc = hit.Parent:FindFirstChild("Humanoid")
        			if npc and not game.Players:GetPlayerFromCharacter(npc.Parent) then
        				npc:TakeDamage(damage)
        				newBullet:Destroy()
        			end
        		end)
        		break 
                wait()  -- keep this here or try moving wait(cooldown) here if wait() doesn't solve the problem
        	end
        	wait(cooldown)
        end)

I’ve done it like this and I have literally no idea why is it still crashing.

local repStorage = game:GetService("ReplicatedStorage")
local bullet = repStorage.Bullet
local gun = script.Parent
local uis = game:GetService("UserInputService")
local player = game.Players.LocalPlayer

local damage = 10
local speed = 100
local cooldown = 1

uis.InputChanged:Connect(function(input, gpe)
	local pressed = uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
	while wait(cooldown) do
		if pressed == true and gpe == false then
			local newBullet = bullet:Clone()
			newBullet.Position = gun.Position + gun.CFrame.LookVector * 5
			newBullet.Parent = game.Workspace

			newBullet.Velocity = gun.CFrame.LookVector * speed
			local bodyForce = Instance.new("BodyForce")
			bodyForce.Force = Vector3.new(0, newBullet:GetMass() * workspace.Gravity, 0)
			bodyForce.Parent = newBullet

			newBullet.Touched:Connect(function(hit)
				local npc = hit.Parent:FindFirstChild("Humanoid")
				if npc and not game.Players:GetPlayerFromCharacter(npc.Parent) then
					npc:TakeDamage(damage)
					newBullet:Destroy()
				end
			end)
		end
	end
end)

Cant find any other solutions, maybe you have to rewrite it I guess.

You could ask another advanced programmer though

It could be because the touched event is firing multiple times, trying using a print statement inside the touched event to see how many times its printing…

Touch event doesn’t even happen, Studio crashes right when I click to shoot. Right now I have something like this and it crashed even though I saw some errors.

local repStorage = game:GetService("ReplicatedStorage")
local bullet = repStorage.Bullet
local gun = script.Parent
local uis = game:GetService("UserInputService")
local player = game.Players.LocalPlayer

local damage = 10
local speed = 100
local cooldown = 1

function shoot(input, gpe)
	local pressed = uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
	if pressed == true and gpe == false then
		local newBullet = bullet:Clone()
		newBullet.Position = gun.Position + gun.CFrame.LookVector * 5
		newBullet.Parent = game.Workspace

		newBullet.Velocity = gun.CFrame.LookVector * speed
		local bodyForce = Instance.new("BodyForce")
		bodyForce.Force = Vector3.new(0, newBullet:GetMass() * workspace.Gravity, 0)
		bodyForce.Parent = newBullet

		newBullet.Touched:Connect(function(hit)
			local npc = hit.Parent:FindFirstChild("Humanoid")
			if npc and not game.Players:GetPlayerFromCharacter(npc.Parent) then
				npc:TakeDamage(damage)
				newBullet:Destroy()
			end
		end)
		wait(cooldown)
		shoot(input, gpe)
	end
end

uis.InputChanged:Connect(shoot())

May not be the fix but…

Try doing

local bullet = repStorage:WaitForChild(“Bullet”)

intead of

local bullet = repStorage.Bullet

I doubt so, but it would be a better way to call for the bullet.

Also for Players try

local player = game:GetService(“Players”).LocalPlayer


more stable

1 Like

You saw some errors? What is it? Check the output if it says something.

Ok, I think that was the issue. It doesn’t respect the cooldown but it doesn’t crash at least. Thank you very much.

1 Like

They were just script errors, fixed them.

You are welcome, glad to help, just dm me if you need anything else.

Yeah, you cannot guarantee that the contents in ReplicatedStorage will be replicated to the client immediately so you should always use :WaitForChild() when wanting to reference something in ReplicatedStorage from the client.

1 Like

It takes time to load too so that is probably why as not everything loads when a char is added.

1 Like