Gun System Anti-Cheat False Positive

I created a gun system using a RemoteEvent that passes the result of a client-sided RayCast to the server but it can be easily exploited by using fake arguments.

To counter this, I had it make a RayCast on the server script with the same properties as the client and check if the result is the same as the client’s result and if it is not, it will kick the player.

There is one major issue though. The delay between the first RayCast being made and the second makes the two RayCasts have different results causing the Anti-Cheat to kick the player if they are moving too quickly.

Client:

function Raycast(mouseHit)
	spawn(function()
		Event:FireServer(gun, Hit, Position, Normal, settings, IgnoreCheck, mouseHit)

		return;
	end)
end

Server:

local function FireGun(Player, Tool, Hit, Position, Normal, Module, IgnoreCheck, mouseHit)
	local RayCast = Ray.new(Tool:FindFirstChild('Handle').Position, (mouseHit-Tool:FindFirstChild('Handle').Position).unit*Module.Bullet_Velocity)
	local ignore = {Tool, Tool.Parent}
	local _Hit, _Position, _Normal = game:GetService('Workspace'):FindPartOnRayWithIgnoreList(RayCast, ignore, false, true)

	if (_Hit ~= Hit) then
		return Player:Kick('Gun cheats detected!')
	end
end

Is there a way to have less delay between the two casts?

Should I instead secure it differently and if so, how would I?

1 Like

I have also tried the RayCast position of the two instead of hit and it still false positives

if ( (_Position - Position).Magnitude > 10 ) then
	return Player:Kick('Gun cheats detected!')
end
1 Like

You’re effectively just checking twice for no reason. Why don’t you just raycast on the server and get rid of your client cast?

1 Like

Part of my gun system requires it. I do not want this to be a debate but rather a support forum. Is there any way you can help me with the script I have at the moment?

1 Like