Any way to make velocity/acceleration calculations more accurate? Help with exploit catching & reversing loop

Hello,
I’m currently working on a system, that can some-what reliably catch speed and teleportation exploits, and teleport players back, but I’m struggling a little on getting accurate results, as well as actually making flight catching…

I’m using a Heartbeat event and it’s provided delta time to calculate velocities, and it works some-what well for XZ velocities, usually ± 5 stud deviation from humanoids walk speed, and if any anomaly is detected - I send them back to last safe position.

Idea with acceleration/ jerk/ difference in velocity was to check, weather player is affected by gravity, because if he wasn’t, it would be pretty clear that player was forcing himself to stay up, aka, flying.
Problem is, i’m getting some really inconsistent data, and I’m not sure how to interpret it/ what am I doing wrong…

Code:

RunServ.Heartbeat:Connect(function(timeElapsed) 
	for i, player in ipairs(game.Players:GetPlayers()) do
		local char = player.Character
		if char and timeElapsed then
			local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
			local humanoid = char:FindFirstChild("Humanoid")
			if humanoidRootPart and humanoid then
				if playerData[player] and humanoid.Health > 0 then
					local lastTimeElapsed = playerData[player].lastTimeElapsed
					local lastPos = playerData[player].lastPosition
					local lastLastPos = playerData[player].lastLastPosition
					local lastStandPos = playerData[player].lastStandingPosition
					local currentPos = humanoidRootPart.Position
					local Standing = isStanding(char)
					
					local Velocity = Vector3.new()
					if lastPos then
						Velocity = (currentPos - lastPos)/timeElapsed
					end
					local VelocityXZ = Round(Vector3.new(Velocity.X, 0, Velocity.Z).Magnitude, 3)
					
					playerData[player].lastPosition = currentPos
					playerData[player].lastTimeElapsed = timeElapsed
					playerData[player].lastLastPosition = lastPos
					if Standing == true then
						playerData[player].lastStandingPosition = currentPos
					end
					
					print(VelocityXZ, Velocity.Y, workspace.Gravity * timeElapsed)
					if VelocityXZ > Default_Walk_Speed + Max_Allowed_Speed_Variation then
						teleportToLastPos(player, lastPos, lastStandPos)
					end
				end
			end
		end
	end
end)

Output:
Screenshot_33

I thought that Velocity.Y should change based on gravitational acceleration, which, at that scale is seen on the right side, but it clearly fluctuates?!

How can I get more accurate data? How does Roblox itself do it?

BTW: I did print(Velocity.Y, humanoidRootPart.Velocity.Magnitude) and it’s clearly smoother:
Screenshot_34

1 Like

Originally on my quest to make the ultimate fall damage I tried deriving acceleration from the velocity, the velocity from the position, and as you said, yuck!

I can only offer the tad bit of advice: take the velocity mag at face value, don’t extrapolate. The physics is internal, and at a different step than whatever choice is of your picking provided to us developers.

Your readings aren’t perfect for a variety of reasons. Cough Humanoids. I came up with the same thing and was freaking out a year ago. In sum vel.mag is the best you’re going to get as far as I know.

2 Likes

Maybe you can use the physics engine to your advantage. Attach a invisible part to the humanoid root part with a spring or rope and find said part’s speed instead of the player’s. any jerky movement or teleports will make the part fling around at high speeds making exploit detection easier, or maybe the part will pull the player back to their original position if the part is heavy enough.

That would effect normal gameplay, attaching parts will effect player movement.

Getting the Distance travelled over a time is a good way to read it. Overall once a player starts going above a legitimate velocity set their velocity to 0 and teleport them back to their last location in case its a fling glitch. If they have been teleported and their velocity goes above normal values again within a time then they must be exploiting.

Another useful thing is to use a datastore, so when players have illegal velocities it will add on to the datastore, after a few get added on the player can be prevented from playing the game until the data is reviewed. The reason we don’t ban them upright for high velocity’s is because this way the system will filter out players being flung by Roblox’s glitchy physics.

Of course certain things being changed or added getting detection could result in a instant ban as there would be no explanation other than exploits. You have to make allowances for bugs and glitches occurring.

Yeah, the pretty much only reason I chose to use positions and derive velocities is I just wanted a one-fits-all solution… I guess it was too good to be true.
But I’ll have to keep the derived velocity too, though, to catch teleportation…

Oh yeah, also velocity doesn’t update if a part is anchored, AFAIK… But if it was anchored, that might also be a clear sign of flight or some shady stuff…

Veocity if calculated from positions would still change Anchored or not.

Theres not really much point in checking if its anchored.