Raycast sanity system

I’ve been making a shooting system for my game but I got stuck on a dilemma, if i make the checking on the client, it’s more precise and more responsive but exploiters can take advantage
if I make it on server it’s safer but less responsive and accurate

so I tried get the best of both worlds, client Raycast, server sanity checks, but idk if the sanity check is exactly that effective
all it does is get the position the client say it as hit and the part it hit, if the distance of the given position and the distance from the part in relation to the server is bigger than a tolerance value, it doesn’t damage, if it’s equal or smaller, it damages
is it good enough or i need change?

1 Like

I’m not the greatest at shooter games but here’s what I would do:
first when the client hits something you do the effects either way then fire a remote function with the part that has been hit and the data used to build the raycast (not all of it some you already know on the server like FilterDescendantInstance).

local raycastResult = workspace:Raycast(Origin, Direction, Params)
if
    raycastResult and
    raycastResult.Instance
    and raycastResult.Instance.Parent:FindFirstChild("Humanoid") then

    DoVFX(...)
    local valid = RemoteFunction:InvokeServer(Origin, Direction, RaycastResult.Instance)
end

On the server, you do regular sanity checks on the raycast data (like the direction isn’t 50000 studs away from the origin or the origin isn’t far far away from the character) if all checks pass you can run that raycast and if the result did hit the part (or atleast the same character) that the player said it did then you return true for valid otherwise false for invalid.

RemoteFunction.OnServerInvoke = function(Player, Origin, Direction, HitPart)
    if
    --3 might be a little too big
    (Origin - Player.Character.Head.Position).Magnitude > 3
    or (Origin - Direction).Magnitude > Range then
        return false
    end

    local raycastResult = workspace:Raycast(Origin, Direction, Params)

    if raycastResult... then
        DoHit(raycastResult.Instance.Parent.Humanoid)
        return true
    end
end

Back on the client, you can use that result to do whatever you want, you can implement a way to cancel the vfx or just say “Raycast validation failed”

...
local valid = RemoteFunction:InvokeServer(Origin, Direction, RaycastResult.Instance)

if not valid then
    Notification("Raycast validation failed")
end

For anticheats you can implement “suspicious behavior” count like save the previous origin and the current and if the difference is way too big and the amount of time that has passed between them isn’t big enough, they could be speed hacking or teleporting, but they could have just been flung so increment the suspicious behavior counter by 1 then once it reaches a certain threshold you can kick the player. A ban isn’t really useful since most cheaters are alting but you could check the suspected player’s inventory or stats to see if this is their main, usually this means they aren’t actually hacking, but if they are kicked many times then you can ban them.

3 Likes

Biggest yap session of my life (I was procrastinating working by writing that)

2 Likes

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