Why are the client-sided and Serversided raycasts different?

I am making a Hitscan gun system, and for some reason when i do a sanity check on the server to make sure the player isnt hacking, it is more accurate than the client?

Client:

local bullet = require(game.ReplicatedStorage.Modules.Bullet)
local mouse = game.Players.LocalPlayer:GetMouse()
local remotes = game.ReplicatedStorage.Remotes
local tool = script.Parent.Parent

local config = {
FirePart = script.Parent,
Damage = 5,
Sound = game.ReplicatedStorage.SFX.Gun,
}

script.Parent.Parent.Activated:Connect(function()
local dir = mouse.Origin.LookVector
local pos = config.FirePart.Position

local rayparams = RaycastParams.new()

rayparams.FilterType = Enum.RaycastFilterType.Exclude
rayparams.FilterDescendantsInstances = {game.Players.LocalPlayer.Character, tool, game.Workspace.Bullets}

local rayResult = workspace:Raycast(pos, dir * 100, rayparams)
bullet.New(dir, pos)

if rayResult then
if rayResult.Instance ~= nil then
remotes.Inflict:FireServer(rayResult.Instance.Parent, config, dir, rayparams)
end
else
warn(“No Instance found.”)
end
end)

Server:

local rs = game:GetService(“ReplicatedStorage”)
local remotes = rs.Remotes

remotes.Inflict.OnServerEvent:Connect(function(player, target, config, dir, rayparams)
–Sanity Check
local newRay = workspace:Raycast(config.FirePart.Position, dir * 100, rayparams)

if newRay then

  print(target)
  print(newRay.Instance.Parent)
  if newRay then
  	if newRay.Instance.Parent == target then
  		print("success")
  else
  	warn("potential hacker detected")
  	end
  end

end
end)

P.S. “bullet.New(dir, pos)” is just an effect function that has nothing to do with the raycast code.

3 Likes

I’m not the best tool in the shed but If you’re making a hit detection system, why make it dependent on the client at all? Wouldn’t that make it more suscepteble to exploits?

3 Likes

This may be due to network lag.

It’s likely that when the server checks the raycast, the client is already in a different position from when the client originally raycasted. So this isn’t an issue of accuracy, as both are technically 100% accurate, but just in different times.

As for this question:

Theoretically, yes, but lag once again poses a problem.
There would be significant delay from you clicking your mouse to the gun firing. It would ruin gameplay, which is why you do it on the client and have the server check the result, so that the result is instant on your end.

Anyway, this is still a tough question to solve. Most games use lag compensation to time travel backwards to the client’s perspective at that time, and do the raycast then and there.

There’s two primary methods for time travel:

  • Interpolation: This is by far most accurate, and is what games like Counter-Strike use. However, it’s also the most difficult to get working. The steps are fairly simple:

    • Every frame, create a snapshot of everything important in your game. Primarily, look angles and character hitbox positions.
    • When the server needs to validate a raycast, it will find the earliest and latest snapshot available, then interpolate to get the best inbetween state. From there, it can raycast with the client’s accuracy.
  • Extrapolation: This is less accurate, but it’s simpler to get going. I don’t know any games that make use of it, because it’s not that good in a competitive scenario and can fail in some situations. But it works like this:

    • When the server needs to validate a raycast, it will take into consideration everyone’s movement velocity.
    • It then virtually moves everyone by v * t, where v is the regarded player’s velocity and t is the client’s ping

    The resulting state is a rough approximation of the client state when they did the raycast.

This is a quick overview, and I won’t get into how to integrate this into code (too lazy lol). It’s just a starting point from which you can base your system.

2 Likes

Hi, i appreciate your detailed response, is it possible that when the server checks the raycast, that i could send the position the player was in when firing the raycast on the client instead of where they are when the server checks?

1 Like

Yes, but the idea is that the entire state of the game was different when the player fired their shot vs. when the server responds.

Besides, you can’t trust the client. Anything can be spoofed, so you basically have to treat all data provided by the client as false until proven true. If you let the client send the position they were in, a hacker could spoof that parameter and “teleport” behind people in games and just kill them instantly.

And also, if you have your lag compensation system properly done, it’s possible to have to send no data from the client (well, maybe not none, the client’s camera CFrame may come in useful).

1 Like

Out of curiosity, do you know of any good open source lag compensation systems or any good youtube tutorials?

I went looking around, and found this:

Might be worth looking into.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.