Gun recoil glitching and crashing?

I’m trying to make a fps framework, but while making the recoil, I’ve came across this problem wich is, if you are using a full-auto gun and you hold for 5 seconds, the game will crash. Also, if you move when shooting, it will make a very weird glitch on the viewmodel (assuming it didn’t crash yet). Here’s a recording:


As you can see, I shot some times, and it was perfect. But then I started moving, and the viewmodel glitched. Then I hold my button and the game crashed. So here’s my script:

local RS = game.ReplicatedStorage
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")

local Values = RS:WaitForChild("Values")
local Modules = RS:WaitForChild("Modules")
local ViewModels = RS:WaitForChild("ViewModels")
local Remotes = RS:WaitForChild("Remotes")

local CurrentCamera = game.Workspace.CurrentCamera



local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local Char = player.Character

local walking = false
local shooting = false

local GunBobCF = CFrame.new()
local RecoilCF = CFrame.new()

local currentPrimary

local function setup(weapon)
	
	local view = ViewModels[weapon]:Clone()
	
	view.Parent = CurrentCamera
	
	currentPrimary = weapon
	
end

local function shoot()
	
	local module = require(Modules[currentPrimary])
	local Origin = ViewModels[currentPrimary].Weapon.Origin

	if module.FireType == "Auto" then

		while shooting do
			
			local damage
			
			local tweenInf = TweenInfo.new(60/module.RPM)
			
			--[[for i = 1,20 do -- initial camera knockback
				
				CurrentCamera.CFrame = CurrentCamera.CFrame * CFrame.Angles(math.rad(0.2),0,0) -- bumping up the camera
				
			end]]
			local RecoilTween = TweenService:Create(CurrentCamera,tweenInf,{CFrame = (CurrentCamera.CFrame * CFrame.Angles(math.rad(2),0,0))})
			RecoilTween:Play()
			
			local rayHit = Ray.new(Origin.CFrame.p,(mouse.Hit.p - Origin.CFrame.p).unit * 999)
			local hit, position = workspace:FindPartOnRayWithIgnoreList(rayHit,
				{
					
					CurrentCamera,
					Char				
					
				}
			)
			
			if hit then
				
				if hit.Parent:FindFirstChild("Humanoid") then
					
					if hit.Name == "Head" then
						
						damage = module.HSDamage
						
					elseif string.find(hit.Name,"Leg") then
						
						damage = module.LegDamage
						
					else
						
						damage = module.Damage
						
					end
					
				end
				
				print(hit.Name)
				Remotes.Shoot:FireServer(damage,hit,position)
				
				wait(60/module.RPM)
				
				--[[for i = 1,10 do -- camera knockback recovery
					
					CurrentCamera.CFrame = CurrentCamera.CFrame * CFrame.Angles(math.rad(-0.1),0,0)
					game:GetService("RunService").Heartbeat:Wait()
					
				end]]
				
				local UnRecoilTween = TweenService:Create(CurrentCamera,tweenInf,{CFrame = (CurrentCamera.CFrame * CFrame.Angles(math.rad(-2),0,0))})
				UnRecoilTween:Play()
			end
			
		end	
		
	elseif module.FireType == "Semi" then
		
		local damage
		
		for i = 1,20 do -- initial camera knockback
			
			CurrentCamera.CFrame = CurrentCamera.CFrame * CFrame.Angles(math.rad(0.2),0,0) -- bumping up the camera
			
		end
		
		local rayHit = Ray.new(Origin.CFrame.p,(mouse.Hit.p - Origin.CFrame.p).unit * 999)
		local hit, position = workspace:FindPartOnRayWithIgnoreList(rayHit,
			{
				
				CurrentCamera,
				Char				
				
			}
		)
		
		if hit then
			
			if hit.Parent:FindFirstChild("Humanoid") then
				
				if hit.Name == "Head" then
					
					damage = module.HSDamage
					
				elseif string.find(hit.Name,"Leg") then
					
					damage = module.LegDamage
					
				else
					
					damage = module.Damage
					
				end
				
			end
			
			print(hit.Name)
			Remotes.Shoot:FireServer(damage,hit,position)
			
			wait(60/module.RPM)
			
			for i = 1,10 do -- camera knockback recovery
				
				CurrentCamera.CFrame = CurrentCamera.CFrame * CFrame.Angles(math.rad(-0.3),0,0)
				game:GetService("RunService").Heartbeat:Wait()
				
			end
			
		end
		
	end
	
end

-- INITIALIZATION

setup("AK47")

UIS.MouseBehavior = Enum.MouseBehavior.LockCenter
UIS.MouseIconEnabled = false

CurrentCamera.CameraType = Enum.CameraType.Scriptable

RunService.RenderStepped:Connect(function(deltaTime)
	
	local viewmodel = CurrentCamera[currentPrimary]
	
	if viewmodel then
		
		mouse.TargetFilter = CurrentCamera
		
		viewmodel.PrimaryPart.CFrame = (
			
			CurrentCamera.CFrame *
			GunBobCF

		)
		
		if walking then
			
			GunBobCF = GunBobCF:Lerp(CFrame.new(
				0.08 * math.sin(tick() * 6), --intensity left/right * math.sin(tick() * speed)
				0.04 * math.sin(tick() * 12), --intensity up/down * math.sin(tick() * speed)
				0
				), 0.1)
			
		end
		
	end
	
end)

mouse.Button1Down:Connect(function()
	
	shooting = true
	shoot()

end)

mouse.Button1Up:Connect(function()
	
	shooting = false

end)

Char:WaitForChild("Humanoid").Running:Connect(function(speed)
	
	if speed > 0.1 then
		
		walking = true
		
	else
		
		walking = false
		
	end
	
end)

Thanks in advance!

1 Like

Game crashes occur while you are using a loop without using the :Wait() function. The two best ways to solve this is:

while condition and wait() do
--function
end
while condition do
wait()
--function
end

I actuallly did wait there, but I just noticed it’s under the hit check, so when I shot to the sky (nothing hit) it doesn’t go through the wait. So I fixed that, and it’s not crashing anymore. BUT the viewmodel glitch is still happening. Do you know a way to fix that?

Are you also using a while loop with a wait() for it? If so, perhaps the RenderStepped listener of RunService would favor better? It executes prior to a new frame being rendered, usually recommended for animations.
For example

local Count = 0; -- A counter variable to count the number of frames pre-rendered

RunService.RenderStepped:Connect(function() -- Connect the RenderStepped listener
    Count += 1; -- Add 1 to the counter
end);

while (true) do
    print("A count of", Count, "frames pre-rendered this second"); -- Output `A count of X frames pre-rendered this second`, X being the name of frames countered
    Count = 0; -- Reset the counter for the next frame count
    wait(1); -- Wait 1 second
end

I am using RenderStepped to move the viewmodel along with the camera, and also for the movement bob using lerp. The recoil is played on the loop with a wait using tweenservice. I already tried to make the loop change the RecoilCF value in the commented line:

RunService.RenderStepped:Connect(function(deltaTime)
	
	local viewmodel = CurrentCamera[currentPrimary]
	
	if viewmodel then
		
		mouse.TargetFilter = CurrentCamera
		
		viewmodel.PrimaryPart.CFrame = (
			
			CurrentCamera.CFrame *
			GunBobCF
            -- * RecoilCF

		)
		
		if walking then
			
			GunBobCF = GunBobCF:Lerp(CFrame.new(
				0.08 * math.sin(tick() * 6), --intensity left/right * math.sin(tick() * speed)
				0.04 * math.sin(tick() * 12), --intensity up/down * math.sin(tick() * speed)
				0
				), 0.1)
			
		end
		
	end
	
end)

But that just somehow flinged the viewmodel.

Don’t use TweenService for camera movement. TweenService moves the camera CFrame from one point to another, so if the player is moving the camera at all (by moving their character or their mouse), there will be an offset. I’m pretty sure this is what is causing your problem.

Alright, but I really don’t know what to do, I’ve been trying to make a recoil effect for 1 week, and I used literally every method you could think of. The recoil in the video was the exact effect I wanted, so I really tought I’d be able to do that with TweenService. By any chance, you know how’d I make it??