How should I validate whether a client-sided raycast hits the target? I want to make sure that if an exploiter tries to fabricate a hit, the server is able to discern whether it is a valid hit or not. What data should I send to the server?
For reference, my current client-sided raycast is below:
local function CastBolt(X, Y, Length)
--Server validation data
local Server = {} --What should I send to the server?
--Cast the ray
local MouseRay = Camera:ScreenPointToRay(X, Y)
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Tool.Parent}
Params.FilterType = Enum.RaycastFilterType.Blacklist
local Result = game.Workspace:Raycast(MouseRay.Origin, MouseRay.Direction*Length, Params)
--Get EndPos based on whether the ray hits
local StartPos = Character:FindFirstChild("HumanoidRootPart").Position
local EndPos
if Result then
EndPos = Result.Position
else
EndPos = MouseRay.Origin + MouseRay.Direction*Length
end
--Draw lightning bolt
coroutine.wrap(function()
local Bolt = BoltCreator:Draw(StartPos, EndPos, 10)
Bolt.Parent = game.Workspace:FindFirstChild("Projectiles")
for _,Obj in pairs(Bolt:GetChildren()) do
if Obj:IsA("BasePart") then
local Effect = Tween:Create(Obj, TweenInfo.new(0.1, Enum.EasingStyle.Sine), {Transparency=1})
Effect:Play()
Effect:Destroy()
end
end
end)()
coroutine.wrap(function()
local Bolt = BoltCreator:Draw(StartPos, EndPos, 10)
Bolt.Parent = game.Workspace:FindFirstChild("Projectiles")
for _,Obj in pairs(Bolt:GetChildren()) do
if Obj:IsA("BasePart") then
local Effect = Tween:Create(Obj, TweenInfo.new(0.1, Enum.EasingStyle.Sine), {Transparency=1})
Effect:Play()
Effect:Destroy()
end
end
end)()
CreateBoltEvent:FireServer()
end
It is impossible for the server to validate whether a client sided raycast is legit because the parameters that would be told to the server are initially coming from the client.
A basic check you can do is that you send the ray on the client, check what the client hit, then verify if the player could’ve hit that part when they were in the position when they shot the ray, also allowing for some latency to show.
You can 100% validate this information. There are many implemtations you can use for the approach which each have their own pros and cons. Here’s my suggestion for high precision, at larger computation cost:
Send the following to the server:
Position the client cast the ray from.
Direction the client cast the ray.
Distance the client said the target was.
Target the client said the ray hit.
On the server you’d preform the following checks (I would re-order these from lowest cost to highest cost, but will explain them in logical order):
Can the server cast a ray from the position the client provided, in the direction the client provided, the distance the cleint said?
Is the client close enough to the point they said they were?
Can the server cast a ray from the client’s current position, to the position they said they were at?
Is the target close to the location the client said it was at (this is the position we just ray cast to)?
Can the server cast a ray from the target’s current position to the location the client said it was at?
Please note “close” is variable. Larger range means more acceptance of latency, but higher potential for exploting the server’s good will. Too low and most calls get rejected due to latency.
The idea behind this psudocode is that we need to check if the raycast itself was valid, then check if the player and target were reasonably in the places they said. You can’t trust simply recasting the ray on the server because things may be moved by the time the message reaches the server.
You can change this implementation to be more preformant with lower fideledy checks too (cut out 2 raycasts by just doing range checks for example) but again doing so opens potential for a client to lie and say they are through a thin wall.
You’ll never truely be able to account for 100% of scenarios, but I hope this one idea gives you ideas on how you can implement a solution that works for you.
I’ve seen some very useful replies here. If the delay between firing a RemoteEvent to RayCast on the server is unacceptable, go for them.
In general I’d suggest to only do visual things on the client in something like this. For example, if you make a laser pointer for your gun, if an exploiter decides to mess with it no one will care.