How do i make my raycast more accurate?

so i have a war game and my guns work pretty swell… although there is just one problem. they are very inaccurate. and i know it looks like a skill issue but sometimes even when i slow it down it still looks like a hit, here it is? and if it is a skill issue how do i make the bullets hit more accurate? (i also played with my friends and it is even more inaccurate!)

heres my module script and local script

(dont flame me this is a old game of mine im coming back to and its very messy…)


local replicatedstorage = game.ReplicatedStorage
local serverstorage = game.ServerStorage
local debris = game:GetService("Debris")

local fireEvent = replicatedstorage.fireremote
local raysFolder = workspace.Rays
local damageindicatorModule = require(serverstorage.Modules.DamageIndicatorModule)


function gunModule.shoot(tool, endposition, startposition, player)
	local range = tool:GetAttribute("range")
	local damage = tool:GetAttribute("damage")
	local headshotDamage = tool:GetAttribute("headshotDamage")

	

	local direction = (endposition - startposition).Unit * range

	tool.Handle.Fire:Play()

	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.FilterDescendantsInstances = {tool,player.Character}

	local raycast = game.Workspace:Raycast(startposition, direction,raycastParams)
	
	local hitPoint = endposition
	

	if raycast and raycast.Instance  then
		print(raycast.Instance.Name)
		


		local hitChar = raycast.Instance.Parent
		local humanoid = hitChar:FindFirstChild("Humanoid")
		
		

		
		
		
		if raycast.Instance then
			if raycast.Instance.Parent:IsA("Accessory")  then
				if  raycast.Instance.Parent.Name == "hel met" then
				else
					table.insert(raycastParams.FilterDescendantsInstances,raycast.Instance.Parent)
				end
			end
		end
		

		
		if raycast.Instance.Parent.Name == "hel met" then
			print(raycast.Instance.Parent.Name)
			hitPoint = raycast.Position
			local helmetHit = game.ServerStorage.helmetHit:Clone()
			helmetHit.Parent = raycast.Instance.Parent.Parent.Head
			helmetHit:Play()
			raycast.Instance.Anchored = false
			damageindicatorModule.show(raycast.Instance.Parent.Parent,0)
			raycast.Instance.Parent = workspace
			raycast.Instance.Velocity = raycast.Instance.Velocity + Vector3.new(10,25,0)
			raycast.Instance.Orientation = Vector3.new(math.random(1,360),math.random(1,360),math.random(1,360))
		
			game:GetService("Debris"):AddItem(helmetHit,1.125)
			game.Debris:AddItem(raycast.Instance.Parent,4)
		end
		

	
		if humanoid then
			
			
			if hitChar.Name ~= player.Character.Name and hitChar.Humanoid.Health > 0 then
				
				if raycast.Instance.Name == "Head" then
					
					local randomHit = serverstorage.randomImpacts:GetChildren()[math.random(1,#serverstorage.randomImpacts:GetChildren())]:Clone()
					randomHit.Parent = raycast.Instance
					randomHit:Play()
					debris:AddItem(randomHit,randomHit.TimeLength)
					humanoid.Health = humanoid.Health - headshotDamage
					damageindicatorModule.show(hitChar,headshotDamage)
					hitPoint = raycast.Position
					local headshothighlight = Instance.new("Highlight", raycast.Instance)
					headshothighlight.DepthMode = Enum.HighlightDepthMode.Occluded
					headshothighlight.OutlineTransparency = 1
					game:GetService("Debris"):AddItem(headshothighlight,0.25)
					
				else
					
					if raycast.Instance.Name == "HumanoidRootPart" then
						local randomHit = serverstorage.randomImpacts:GetChildren()[math.random(1,#serverstorage.randomImpacts:GetChildren())]:Clone()
						randomHit.Parent = raycast.Instance
						randomHit:Play()
						debris:AddItem(randomHit,randomHit.TimeLength)
						humanoid.Health = humanoid.Health - damage
						damageindicatorModule.show(hitChar,damage)
						hitPoint = raycast.Position
						if raycast.Instance.Parent:FindFirstChild("Torso") then
						local highlight = Instance.new("Highlight", raycast.Instance.Parent.Torso)
						highlight.DepthMode = Enum.HighlightDepthMode.Occluded
						highlight.OutlineTransparency = 1
						game:GetService("Debris"):AddItem(highlight,0.25)
						end
					else
						
						local randomHit = serverstorage.randomImpacts:GetChildren()[math.random(1,#serverstorage.randomImpacts:GetChildren())]:Clone()
						randomHit.Parent = raycast.Instance
						randomHit:Play()
						debris:AddItem(randomHit,randomHit.TimeLength)
						humanoid.Health = humanoid.Health - damage
						damageindicatorModule.show(hitChar,damage)
						hitPoint = raycast.Position
						local highlight = Instance.new("Highlight", raycast.Instance)
						highlight.DepthMode = Enum.HighlightDepthMode.Occluded
						highlight.OutlineTransparency = 1
						game:GetService("Debris"):AddItem(highlight,0.25)
					end
				end
				if hitChar.Humanoid.Health <= 0 then
					
					print("dead killed by ".. player.DisplayName)
					player.leaderstats.kills.Value += 1
				end
			end
		end
	end
end

return gunModule

local players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local replicatedstorage = game.ReplicatedStorage

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

local tool = script.Parent
local sound = tool:WaitForChild("Handle"):WaitForChild("reload")
local fireEvent = replicatedstorage:WaitForChild("fireremote")
local reloadEvent = replicatedstorage:WaitForChild("reloadEvent")
local raysFolder = workspace.Rays
local debris = game:GetService("Debris")

local fireCooldown = false
local cooldownTime = tool:GetAttribute("cooldown")
local ammo = tool:GetAttribute("ammo")
local ammoAmount = tool:GetAttribute("ammoAmount")
local recoil = tool:GetAttribute("recoil")

mouse.TargetFilter = raysFolder
mouse.TargetFilter = tool
mouse.TargetFilter = player

local shooting = false
local canShoot = true
local clickCooldown = false
local reloading = false
local equipped = false

local idleAnimation = script:WaitForChild("idle")
local track

local function click()
	if not clickCooldown then
		clickCooldown = true
		if tonumber(ammoAmount) <= 0 then
			print("click")
			tool.Handle.click:Play()
		end
		task.wait(0.25)
		clickCooldown = false
	end
end



tool.Equipped:Connect(function()
	track = player.Character.Humanoid:LoadAnimation(idleAnimation)
	track:Play()
	tool.Enabled = true
	canShoot = true
	equipped = true
	player.PlayerGui.ammo.Enabled = true
	player.PlayerGui.ammo.TextLabel.Text = ammoAmount .. "/" .. ammo

	UserInputService.InputBegan:Connect(function(input, isProcessed)
		if not isProcessed and equipped and not shooting then
			if input.KeyCode == Enum.KeyCode.R then
				if not reloading then
					reloading = true
					shooting = false
					print("reload")

					print(sound.TimeLength)
					reloadEvent:FireServer(tool,sound)
					task.wait(sound.TimeLength)
					ammoAmount = tonumber(ammo)
					player.PlayerGui.ammo.TextLabel.Text = ammoAmount .. "/" .. ammo
					reloading = false
				end
			end
		end
	end)
	if script.Parent:WaitForChild("auto").Value == true then
		mouse.Button1Down:Connect(function()
			if canShoot and not shooting and not reloading then
				shooting = true
				canShoot = false

				while shooting do
					wait()
					canShoot = true
					if not fireCooldown and canShoot then
						if tonumber(ammoAmount) > 0 then
							fireCooldown = true
							local range = tool:GetAttribute("range")

							camera.CFrame = camera.CFrame:Lerp(camera.CFrame * CFrame.Angles(math.rad(recoil),math.rad(recoil),math.rad(recoil)),0.1)
							ammoAmount = ammoAmount - 1



							local startPosition = tool.Start.Position
							local endPosition = mouse.Hit.Position
							local direction = (endPosition - startPosition).Unit * range

							local hitPoint = endPosition
							local bolt = tool.Handle.bolt
							local unbolt = tool.Handle.unbolt
							player.PlayerGui.ammo.TextLabel.Text = ammoAmount .. "/" .. ammo

							fireEvent:FireServer(tool, startPosition, endPosition)

							wait(cooldownTime)

							fireCooldown = false
						else
							click()
						end
					end
				end
			end
		end)
	else
		tool.Activated:Connect(function()
			if not fireCooldown and not reloading then
				if tonumber(ammoAmount) > 0 then
					fireCooldown = true
					local range = tool:GetAttribute("range")

					ammoAmount = ammoAmount - 1

					camera.CFrame = camera.CFrame:Lerp(camera.CFrame * CFrame.Angles(math.rad(recoil),math.rad(recoil),math.rad(recoil)),0.1)

					local startPosition = tool.Start.Position
					local endPosition = mouse.Hit.Position
					local direction = (endPosition - startPosition).Unit * range

					local hitPoint = endPosition
					local bolt = tool.Handle.bolt
					local unbolt = tool.Handle.unbolt
					player.PlayerGui.ammo.TextLabel.Text = ammoAmount .. "/" .. ammo

					fireEvent:FireServer(tool, startPosition, endPosition)

					task.wait(cooldownTime)

					fireCooldown = false
				end
			elseif tonumber(ammoAmount) <= 0 then
				click()
			end
		end)
	end

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




tool.Unequipped:Connect(function()
	tool.Enabled = false
	equipped = false
	shooting = false
	canShoot = false
	player.PlayerGui.ammo.Enabled = false
	if track then
		track:Stop()
	end
end)

you are making the raycasts on the server, which means when the player clicks, the time before the remoteevent firing will provide a delay, meaning it will get the wrong target. Basically, you have to rewrite some of your code and do raycasts on the client and send that raycasts information to the server.

hmmm alright ill do this… definitely makes sense

Have you found a solution? I came across this one day too and still can’t figure out if it just the delay or my reaction time, the scheduler-priority seem to says very differently

I know that everything that is send to the server or to the client is at the last time of the frame ( Replication Send Jobs ) and that include character position.

The server would then do the Replication Receive Jobs and update accordingly and If I were to consider that Character Position is updated first before event is proceeded then I would think it a total reasonable miss. Still considering ping and stuff and your reaction time

Says you have 100ms ping ( average for me ) and 100ms reaction time + maybe 100ms for you to move your mouse and fire it and then some more unnoticeable delay from your mouse input to your computer and from the code to process it and act accordingly to fire the remote and depend on your code then that would be ~301ms. While all of that is happening the server is currently having to do something too such as updating character position and movement, so that mean your last seen scene may not be the same as the server scene. I think so, I still think am missing something here or just giving out misinformation I have done my testing but I don’t think I can trust the test, I do try to fire a bit ahead of the target at it seem to hit higher than putting it right on the target is the target if it was to constantly moving so I don’t know.

In the video you send going through frame by frame I see you “kinda” miss the framerate isn’t great so I am still unsure.

No im still trying to find a fix… please reply if u find one!

yeah i do miss alot, but ive been testing some more and ive had points where i know im hitting them and they still are not very accurate (especially with moving characters) i was just wondering if there was a way to make the gun more “accurate” easier to hit your target