I recently found a new method of detecting noclip which might possibly be better than the original (raycast from last position to the newest position), this method doesn’t false flag when increasing the wait time between checks and is fairly simple too, this method works by creating a part within the character which is smaller than the player Torso (to avoid false flags) and every x amount of time it’ll get all the parts touching it excluding the parts within the Player’s character and other Players’s characters then it’ll raycast to the touching parts and if the raycast returns nil then they must be noclipping due to raycasting needing a part face to intersect with.
(it is serverside)
Here is the interesting method:
local Players = game:GetService("Players")
local NoclipPart
local function CreatePart(Character, RootPart, Humanoid) -- function to create NoclipPart
local Connections = {}
local NoclipPart = Instance.new("Part")
NoclipPart.Size = Vector3.new(1.5,1.9,.8) -- set the best possible size without false flags
NoclipPart.CanCollide = true -- cancollide must be true otherwise it won't work
NoclipPart.Name = math.random(1, 9999)
NoclipPart.Parent = Character
local Weld = Instance.new("Weld") -- a weld so the Part stays attached to the RootPart
Weld.Part0 = NoclipPart
Weld.Part1 = RootPart
Weld.Name = math.random(1, 9999)
Weld.Parent = NoclipPart
NoclipPart.Destroying:Connect(function() -- if RejectCharacterDeletions is set to false this'll make sure the part isn't just destroyed
if Humanoid and Humanoid.Health > 0 then -- checks to make sure the Player hasn't died
NoclipPart = CreatePart(Character, RootPart) -- if the player hasn't died then recreate the part
else
for _,connection in pairs(Connections) do -- loop through all connections and disconnect them
connection:Disconnect()
connection = nil
end
end
end)
Weld.Destroying:Connect(function()
if Humanoid.Health and Humanoid.Health > 0 then
if Humanoid and Humanoid.Health > 0 then -- checks to make sure the Player hasn't died
NoclipPart:Destroy()
NoclipPart = CreatePart(Character, RootPart) -- if the player hasn't died then recreate the part
else
for _,connection in pairs(Connections) do
connection:Disconnect()
connection = nil
end
end
end
end)
return NoclipPart
end
Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
NoclipPart = CreatePart(Character, HumanoidRootPart)
while true do
if Humanoid and Humanoid.Health > 0 then -- check to make sure the player hasn't died
for _,Part in pairs(NoclipPart:GetTouchingParts()) do -- loop through all parts touching the NoclipPart
if Part:IsA("Part") and Part.Parent ~= Character and Part.CanCollide == true and not Part.Parent:FindFirstChild("Humanoid") then -- checks to stop false flags
local Origin = NoclipPart.Position
local Direction = Part.Position
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
RayParams.FilterType = Enum.RaycastFilterType.Exclude -- filter out parts within the Player's Character
local RayResults = workspace:Raycast(Origin, Direction, RayParams) -- raycast from the NoclipPart to the touching Part
if not RayResults then -- if the raycast returned nil then they must be inside the part because the raycast found no faces to intersect with
Humanoid.Health = 0 -- punish the player however you please
end
end
end
else
break -- break out of the loop if the player has died
end
task.wait() -- this can be changed but teleport through parts won't be detected anymore
end
end)
end)