Anti-Cheat No Clip Issue

I’m trying to make an anti no clip script with raycasts, but it keeps on erroring with “Unable to cast RaycastResult to ray”.

Basically the script captures the players position from .1 seconds ago to now and casts a ray between those two points to detect if the player walked thought a part.

I left comments on the code to make it easier to read

error happens at the first function

also I’m taking advice on how to make the script better

local CplrPos = {}

function RayPeirce(RayCast)
	-- Checks if the Raycast has nothing that hit it
	if RayCast == nil then return {} end
	local Parts = {}
	local DetectedPart = nil
	
	-- Gets all parts that intersect with the ray
	repeat
		--//ERROR HERE\\
		-- I recive and error here saying "Unable to cast RaycastResult to Ray"
		DetectedPart = game.workspace:FindPartOnRayWithIgnoreList(RayCast,Parts)
		print(DetectedPart)
		table.insert(Parts, DetectedPart)
	until DetectedPart == nil
	
	-- returns all hit parts
	return Parts
end

while wait(.1) do
	--loops throught every player every .1 second
	for i , plr in pairs(game.Players:GetChildren()) do
		-- makes sure the player has a character so it won't error
		if plr.Character then
			local plrpostab = nil
			-- Checks if the player already has data saved
			for i , v in pairs(CplrPos) do
				if v.Player == plr then
					print("Found")
					plrpostab = v
				end
			end
			-- if no data was found then it will create new data for the player and put it into the CplrPos table
			if plrpostab == nil then
				print("Isnil")
				local Table = {
					["Pos"] = plr.Character.HumanoidRootPart.Position;
					["Player"] = plr
				}
				table.insert(CplrPos,Table)
			else
				--//REAL ANTI CHEAT STARTS HERE\\
				local oldpos = plrpostab.Pos
				local newpos = plr.Character.HumanoidRootPart.Position
				-- Gets the direction between the old position and new position
				local direction = newpos + (oldpos-newpos).unit
				-- Gets the distance between those two points
				local distance = (newpos-oldpos).Magnitude
				
				-- normal rayparams stuff
				local rayinfo = RaycastParams.new()
				rayinfo.FilterType = Enum.RaycastFilterType.Blacklist
				rayinfo.FilterDescendantsInstances = {plr.Character}
								
				-- casts a ray with all know info
				local cast = game.Workspace:Raycast(oldpos,direction*distance,rayinfo)
				
				-- gets all parts that intersect with the ray with function made above^^^
				local parts = RayPeirce(cast)
					
				local setnewpos = true
				
				-- moves the player back if they intersect with a part that has can collide false
				for i , v in pairs(parts) do
					if v.ClassName == "Part" then
						if v.CanCollide == true then
							plr.Character.HumanoidRootPart.Position = oldpos
							setnewpos = false
						end
					end
				end
				
				-- temporary just stuff to see the ray
				local par = Instance.new("Part")
				par.Anchored = true
				par.CanCollide = false
				par.Size = Vector3.new(.1,.1,distance)
				par.CFrame = CFrame.lookAt(oldpos,newpos)*CFrame.new(0,0,-distance/2)
				par.Parent = game.Workspace
				--
				
				if setnewpos == true then
					plrpostab.Pos = newpos
				end
			end
		end
	end
end
2 Likes

The function :Raycast() already returns a value by itself, it does not return a ray. If it is intersecting something, it will return it, and if not, it will return nil. In order to work, :FindPartOnRay() needs to be given an actual ray object. Plus, the :FindPartOnRay() is deprecated.

If you do want to use :FindPartOnRay(), you will need to give it an actual Ray object.

Raycast method
The ray object

Yeah… that makes more sense I just implemented it.

That’s great, I assume it’s working now?

1 Like

This one works local CplrPos = {}

– Function to handle ray piercing
local function RayPeirce(raycastResult)
if not raycastResult or not raycastResult.Instance then
return {}
end

local parts = {}
local detectedPart = raycastResult.Instance
local origin = raycastResult.Position
local direction = raycastResult.Normal * -1  -- Invert the normal to get the ray direction

while detectedPart do
    table.insert(parts, detectedPart)
    detectedPart = game.Workspace:FindPartOnRayWithIgnoreList(Ray.new(origin, direction), parts)
end

return parts

end

while wait(0.1) do
for _, plr in ipairs(game.Players:GetPlayers()) do
if plr.Character then
local plrposData = nil

        for _, data in ipairs(CplrPos) do
            if data.Player == plr then
                plrposData = data
                break
            end
        end

        if not plrposData then
            plrposData = {
                Pos = plr.Character.HumanoidRootPart.Position,
                Player = plr
            }
            table.insert(CplrPos, plrposData)
        else
            local oldPos = plrposData.Pos
            local newPos = plr.Character.HumanoidRootPart.Position

            local direction = (newPos - oldPos).unit
            local distance = (newPos - oldPos).Magnitude

            local rayParams = RaycastParams.new()
            rayParams.FilterType = Enum.RaycastFilterType.Blacklist
            rayParams.FilterDescendantsInstances = {plr.Character}

            local raycastResult = game.Workspace:Raycast(oldPos, direction * distance, rayParams)

            local intersectedParts = RayPeirce(raycastResult)

            local setNewPos = true

            for _, part in ipairs(intersectedParts) do
                if part:IsA("BasePart") and part.CanCollide then
                    plr.Character.HumanoidRootPart.Position = oldPos
                    setNewPos = false
                    break
                end
            end

            if setNewPos then
                plrposData.Pos = newPos
            end
        end
    end
end

end