I am working on a project that has been in my mind for a while, but I am afraid that after it’s release it will just be plagued by exploiters changing their character properties or inserting fly/flinging scripts. Is there a way to prevent these sort of exploits, or is it just up to the game moderators themselves?
Yes, there are many free server-sided (and client-sided (wouldn’t recommend these)) anti-cheats and you can also make some yourself if you have the knowledge to do so. Some server-sided anticheats can detect these flying and flinging functions to a very good degree.
For flying/flinging I recommend having a script detecting movement distance, if a player moves too far too fast teleport them back to their old position
I’ll keep this as brief as possible:
You need to keep strict sanity checks at client-server communication endpoints. Kind of like a border patrol.
If you have remote events, make sure you validate your numbers.
For example, many shooter games have to create sanity checks for bullets. Exploiters can instantiate bullets in bizarre locations that may appear alright on the client. To combat this many games test if the path of the bullet is possible or if the bullet is too far away on the server.
Would I check the player’s speed or would I check the MoveDirection?
Yes, I have already locked down my remote events so they can only do stuff in certain conditions, example: only being able to reload the character if they have died.
Check their position/magnitude
here is a script
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
wait(1)
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local firstPos = HumanoidRootPart.CFrame
while wait(1) do
if(firstPos.p - HumanoidRootPart.CFrame.p).Magnitude >= Humanoid.WalkSpeed + 15 then
HumanoidRootPart.CFrame = firstPos
end
firstPos = HumanoidRootPart.CFrame
end
end)
end)
Many exploiters increase the variable fps rate to simulate increased speed, to combat this you could do the following on the client:
local RS = game:GetService("RunService")
local plr = game.Players.LocalPlayer
RS.Heartbeat:Connect(function()
if workspace:GetRealPhysicsFPS() > 61 then
-- plr = exploiter
end
end)
You should also check to see if the humanoid.WalkSpeed or the humanoid.JumpPower is above normal each heartbeat. I would advise against using RenderStepped for detecting exploits.
So using that system, I can detect if they are going faster than their assigned walkspeed, correct?
also, what about flyhacks that aren’t moving at a fast rate? would I use a raycast to detect their distance from the ground instead?
I use a combination of server-sided magnitude checks, like the one that @Azul_Litt posted, as well as boundary checks to make sure a player doesn’t go any higher (or lower) than allowed. If your game has flying vehicles or varying altitudes, boundary checks may not work as well.
Raycasting and seeing how far the player is above the ground seems like the best bet.
Sorry if this is a late reply but I just found this post again so I just made a prototype of @detourious’s idea of raycasting.
Here’s the code: (put a script in ServerScriptService and paste this inside, change values if needed)
--//Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
--//Controls
local maxHeight = 50
--//Tables
local Connections = {}
--//Functions
Players.PlayerAdded:Connect(function(player: Player)
player.CharacterAdded:Connect(function(character: Model)
local HumanoidRootPart: BasePart = character:WaitForChild("HumanoidRootPart")
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local direction = Vector3.new(0, -maxHeight, 0)
Connections[player] = RunService.Stepped:Connect(function()
if not character then
Connections[player]:Disconnect()
return
end
local raycast = workspace:Raycast(HumanoidRootPart.Position, direction, raycastParams)
if not raycast then
--//Player is 50 studs in the air
Connections[player]:Disconnect()
--//Reload player
player:LoadCharacter()
return
end
end)
end)
player.CharacterRemoving:Connect(function()
Connections[player]:Disconnect()
end)
end)
Players.PlayerRemoving:Connect(function(player: Player)
local connection = Connections[player]
if connection then
connection:Disconnect()
end
end)
Place file:
Simple Raycast Anti-Cheat (Server-Sided).rbxl (33.9 KB)
Thanks, I already made a working prototype, but I will use this to make it even better.