Alternative Ways to detect Flying "Exploits"?

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.

3 Likes

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)
2 Likes