Hello Everyone! I am making an fps game an when making the hit detection i stumbled upon raycast lag. Basically if i fire a raycast from the server, it will miss the target
cuz of lag., but on the client it seems fine. I made a way around it which is shooting a ray from the client and if it hit something, it will pass the raycast data via a remote event to the server, Then the server will fire another raycast with the length of the client one. If the distance between the two raycast end point is <= 3 it will register the hit, tho i don’t think this is secure enough. Is this my only option or is there anything i can do to compensate the lag.
You could use a remote function to only raycast on the server and then return if there’s a hit or not, although there will be some latency.
I believe that the current solution you are using is the best and it’s what I have done in the past. While is may not be the most secure, people could still easily aimbot and use ESP if they really wanted to cheat.
One of the ways I saw that valve uses is called rollback networking. Essentially what you want to do is record the state of all entities in the world every x amount of time, and then allow the client to send the time they shot at, so you can then “roll back” the world state and calculate if a hit occurred based on the clients perception of the world. You would typically remove any world state caching after ~2 seconds because a ping of that caliber is the players own problem lol. Since the client can only send the time and the server is still authoritative of all positions it’s fairly secure. The valve developer wiki can probably explain t better than I can: Source Multiplayer Networking - Valve Developer Community
Would def. try it(did some research), so basically what i have to do is record the position of every player lets say every .1 seconds. Then when i fire a shot it saves the time when it was shot(on the client), i suppose if its not perscise i can round it up. So the server basically rewinds to the time the client gave, and if the ray would have hit at that time, it does damage. Atleast this is how i understand it, but i would ask you to elaborate on the last part with the rewinding
Can you maybe give like a 10 liner code sample so i can visualize it better, anyway thanks for the idea a lot, if you don’t feel like elaborating i will try to figure it on my own
EDIT : I tried making a code sample on my own and ended up with this, is it correct?
local Players = game:GetService("Players")
local rollbackCache = {} -- Store past positions of players
-- Record player positions every 0.1 seconds
game:GetService("RunService").Heartbeat:Connect(function()
for _, player in pairs(Players:GetPlayers()) do
if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
local pos = player.Character.HumanoidRootPart.Position
rollbackCache[player.UserId] = rollbackCache[player.UserId] or {}
table.insert(rollbackCache[player.UserId], {time = os.clock(), position = pos})
if #rollbackCache[player.UserId] > 20 then -- Keep only the last 2 seconds (0.1s x 20)
table.remove(rollbackCache[player.UserId], 1)
end
end
end
end)
-- Simulate a hit check with rollback
local function checkHit(playerWhoShot, timeOfShot, hitPosition)
for _, data in ipairs(rollbackCache[playerWhoShot.UserId] or {}) do
if math.abs(data.time - timeOfShot) < 0.05 then -- Find the closest past state
local distance = (data.position - hitPosition).Magnitude
if distance < 5 then -- Assume a hit radius of 5 units
print("Hit registered!")
return true
end
end
end
print("Missed!")
return false
end