Making an anti-noclip/preventing wall glitches

Hello, when I was very new to programming in Roblox Lua, I had no idea how to incorporate raycasting into my models. One problem I had while making a game is that players would get stuck in the walls of the game. To fix this, I decided to use a method which is made for anti-noclip. I tried making this script on my own for about a month but had failed a lot, so I’m hoping this tutorial will help a lot of beginner programmers in combatting exploiting and stopping some bugs.

To get started, you’re going to want to make a new script in ServerScriptService, you can name it anything you’d like. Inside the script, you’re going to put the following script:

Source code
game:GetService("Players").PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		spawn(function()
			local root = char.HumanoidRootPart
			local LastVec = root.Position

			game:GetService("RunService").Heartbeat:Connect(function()
				local r = Ray.new(LastVec, root.Position - LastVec)
				local Hit, Position = workspace:FindPartOnRayWithIgnoreList(r, {char})
				pcall(function()
					if Hit and Hit.CanCollide == true then
						root.CFrame = CFrame.new(LastVec)
					end
				end)
				LastVec = root.Position
				print(LastVec)
			end)
		end)
	end)
end)

Let’s go through what this script does step by step.

game:GetService("Players").PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)

The above script waits for a player to join, and then waits for their character to load.

            local root = char.HumanoidRootPart
			local LastVec = root.Position

			game:GetService("RunService").Heartbeat:Connect(function()

This will assign the variable root to char.HumanoidRootPart, and then keep track of it’s current position in the variable LastVec. The last line will run the function every heartbeat of RunService. I’m not good at explaining how heartbeat works, so feel free to check out this roblox api page on it.

                local r = Ray.new(LastVec, root.Position - LastVec)
				local Hit, Position = workspace:FindPartOnRayWithIgnoreList(r, {char})

This creates a new ray with the humanoid root part’s last position and then fires the ray in the direction of the current position.

                pcall(function()
					if Hit and Hit.CanCollide == true then
						root.CFrame = CFrame.new(LastVec)
					end
				end)
				LastVec = root.Position
				-- print(LastVec)

This piece of code sets the humanoid root part’s CFrame to the last vector recorded only if the ray found a collide-able part intersecting between it, like a wall.
Note: if the player has extreme lag while going around corners, then this may have false positives and send the player back when they were rounding a corner. If this is the case, then this method is not for you.

I hope you enjoyed my first tutorial, feel free to ask any questions or give me criticism in the replies. Thank you for reading : )

Don’t use the deprecated raycasting API, use this method instead.

1 Like

Thanks, I did the code a fairly long time ago.

1 Like

A nitpick, spawn is pretty unnecessary in this situation because connecting to events creates a new “thread” for the callback.

Another nitpick

Pcall is also unnecessary because there is no way to really error there.

  1. Hit can either be nil or something
    a. If nil then it just stops
    b. if something then it checks if hit CanCollide is true which also can’t really error
5 Likes