A common problem today with games is dealing with players who exploit in your game. This is a challenging obstacle to somehow fix in a game. A common exploit, from what I’ve seen, is people using flying exploits to gain advantages in a game. This can be game breaking, and deter players from playing. I wanted to ask if anyone has any ideas or ways of detecting flight through the server.
Answers to possible question: Why not detect flight through the client? Anything on the exploiters client is manipulatable. This being said, the exploiter could hypothetically delete the anti cheat local script and no longer be detected. This, however, is not the case for the server as to why I ask for possible solutions.
I’ve made a very simple script that checks for how long the player has been in the air. It’s very basic, and could probably recieve a lot of improvements.
local RunService = game:GetService("RunService")
local Players = {}
local function GetIsFloating(Player)
local Character = Player.Character
if not Character then
return
end
local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
if not HumanoidRootPart then
--[[
You could probably do a :LoadCharacter call here, usually a player's
character will contain a HumanoidRootPart, but sometimes, it may
not because they've fallen into the void or something. But it's
generally a bit suspicous it they don't have one, as it could be
an attempt to bypass the anti-cheat
]]
return
end
local RayInfo = RaycastParams.new()
RayInfo.FilterType = Enum.RaycastFilterType.Blacklist
RayInfo.FilterDescendantsInstances = {Character}
local Hit = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0, -5, 0), RayInfo)
if Hit then --Player is on the ground
Players[Player.Name].LastOnGroundPosition = HumanoidRootPart.Position
Players[Player.Name].FloatStart = -1
else --Player is above jump height, not really that suspicious
if Players[Player.Name].FloatStart == -1 then
Players[Player.Name].FloatStart = tick()
end
end
end
RunService.Heartbeat:Connect(function()
for _, Player in pairs(game:GetService("Players"):GetPlayers()) do
if not Players[Player.Name] then
Players[Player.Name] = {
LastOnGroundPosition = Vector3.new(0, 0, 0),
FloatStart = -1
}
else
local Character = Player.Character
if Character then
GetIsFloating(Player)
local FloatStart = Players[Player.Name].FloatStart
local FloatTime = tick() - FloatStart
if (FloatStart ~= -1 and FloatTime > 2) then --Player has been in the air for 2 seconds
--[[
It's not that suspicious, so we'll just take away the player's network ownership over their character,
this causes input delay, but we'll immediately give back network ownership when they touch the ground.
Taking network ownership away from the player and giving it to the server will also most likely block
the flying method they used, as a most of the time, physics cheats rely on the player having
complete control of their character.
]]
Player.Character.HumanoidRootPart:SetNetworkOwner(nil)
if FloatTime > 5 then --If they've been in the air for 5 SECONDS, then move them back to where they were last before floating
Character:PivotTo(CFrame.new(Players[Player.Name].LastOnGroundPosition))
end
else
Player.Character.HumanoidRootPart:SetNetworkOwner(Player)
end
end
end
end
end)