Server-Side Fly detection (WITHOUT RAYCASTS)

Hello everyone, today I will be open sourcing a fly detection that I found in 2022-2023.

It’s a really basic detection without raycast’s, I advise not to kick when detected as it could be falsely flagged.

Before anyone starts replying "Oh welllll I can just play an animation or use vfly to bypass it! :nerd_face: ". I know that it’s easy to bypass, detecting 9 year olds with infinity yield on their phone is still better than nothing.

Anyways, enough talk! Here’s the script :

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local MaxFlyTime = 1

local function PlayerAdded(plr : Player) : nil
	plr.CharacterAdded:Connect(function(Character : Model)
		if not plr:HasAppearanceLoaded() then
			plr.CharacterAppearanceLoaded:Wait()
		end

		local HRP : BasePart = Character:WaitForChild("HumanoidRootPart")
		local Humanoid : Humanoid = Character:WaitForChild("Humanoid")
		local Animator : Animator = Humanoid:WaitForChild("Animator")

		local Time = 0

		-- Wait for the animate script to load.
		repeat 
			if #Animator:GetPlayingAnimationTracks() == 0 then
				Time = 0
				task.wait()
			else
				Time += task.wait()
			end
		until Time > 3

		local Suspicious = false
		local Detected = false	
		local LastPosition = HRP.Position

		local FlyingTime = 0
		local IsFlying = false

		RunService.PreSimulation:Connect(function(dt)
			if Detected then
				Character:PivotTo(CFrame.new(LastPosition)) 
				return 
			end

			-- This is not a 100% guaranteed fly detection, can be easily bypassed but is still enough to stop some skids.
			if #Animator:GetPlayingAnimationTracks() == 0 then
				Suspicious = true
				FlyingTime += dt
				if FlyingTime >= MaxFlyTime then
					Detected = true
					FlyingTime = 0

					HRP:SetNetworkOwner(nil)
					Character:PivotTo(CFrame.new(LastPosition))
					HRP.Anchored = true
					task.delay(2, function()
						Detected = false
						HRP.Anchored = false
						HRP:SetNetworkOwner(plr)
					end)
				end
			else
				Suspicious = false
			end

			if not Suspicious then
				LastPosition = HRP.Position
			end
		end)
	end)
end

for _, v in Players:GetPlayers() do
	task.spawn(PlayerAdded)
end

Players.PlayerAdded:Connect(PlayerAdded)

Showcase :

2 Likes

For anyone wondering, I used a modified version of infinity yield to make it work with studio (Using xAPI).

Here’s the source : StudioScripts/InfinityYield5.9.4

If you could, can you show you walking around with other people in the game?

What do you mean by that?

blurred

Wouldn’t constant :SetNetworkOwner() calls result in input lag if the player has high ping?

No, SetNetworkOwner is only called when the player is detected, and even then, the HumanoidRootPart is anchored so it doesn’t make a difference.

Oh alright, thanks for the clarification

1 Like

Here you go I guess. Youtube video