I’m working on building an anti-fly cheat system for my game, and I’m looking for some feedback on my approach. I’ve seen some examples online, but they’re not always effective, so I wanted to come up with something better.
Here’s what I’ve thought of so far:
Fire a raycast towards the below of the character.
If the raycast returns nil, there might be a chance the player is flying.
To avoid false positives, we’ll need to do some extra checks to determine if the player is actually flying or just falling.
So, we’ll raycast again to check if there’s ANY ground below the player, even if it’s far away.
If there is, we can predictably calculate the time it would take for the player to land on that ground.
If the player takes longer to land than the calculated time, there’s a chance they’re exploiting.
I’m planning on adding a couple of seconds to the calculation to account for any potential discrepancies. However, I’m not sure if this will be effective or not, and I would love to hear your thoughts on it.
Also, if you have any other ideas on how to prevent players from flying using exploits, I’d be really interested to hear them.
Well, the first raycast would be somewhere near the character’s legs, and then the second would be like 1000 to 2000 studs down. But I’m scripting an anti-cheat pack so I can later on sell it, so who knows if the seller uses it for a space game.
All I need right now is checking the Y position/velocity but with checks because the player might be falling or anything like that. I have another script that detects whenever the player moves faster than he could (walkspeed changed locally). So that would probably stop exploiters from flying towards X or Z axis.
What I do with my anti-fly is I just check to see if they’re in the air or not and if they are I just verify if they’re falling but if they go up then they’re flying
You can do a raycast from the player’s HumanoidRootPart pointing down for 10 studs. Make sure to use RaycastParams to blacklist the player’s character to avoid false negatives. If the raycast returns nil, get their Y position. Wait a little bit, then get their Y position again. If the second Y is less than the first Y, then they are moving down and are probably falling. You can run the Y check in a loop and raycast again if the current Y is equal to or greater than the previous Y. When that happens, raycast again and if it still returns nil, they are cheating.
local function checkFlying(player)
local char = player.Character
local root = char:FindFirstChild("HumanoidRootPart")
local rayparam = RaycastParams.new()
rayparam.FilterDescendantsInstances = { char; }
rayparam.FilterType = Enum.RaycastFilterType.Exclude
rayparam.IgnoreWater = false
rayparam.RespectCanCollide = true
local downVect = Vector3.new(0, -10, 0)
local result = game.Workspace:Raycast(root.Position, downVect, rayparam)
if result == nil then
task.spawn(function())
local previousY = root.Position
task.wait(0.25)
local currentY = root.Position
while currentY < previousY do
task.wait(0.25)
previousY = currentY
currentY = root.Position
end
result = game.Workspace:Raycast(root.Position, downVect, rayparam)
if result == nil then
player:Kick("Cheating is not allowed on this server.")
end
end
end
end
So basically, if the initial raycast returns nil, this will spawn a thread to keep checking the Y position four times a second. The loop runs for as long as the previous Y is greater than the current Y which indicates that the player is moving down. When that stops being the case, a second raycast is performed. If that one returns nil as well, then they are cheating.