How can you stop a player from camera clipping

How can you push a player back when they put their camera in a wall, Currently, If your player camera walks into a wall, You can see outside the map. What I want to achieve is to make it so it pushes a player back a tiny bit if they try to camera clip, Like in arsenal, Here is a clip from arsenal.

7 Likes

I haven’t tested it, but perhaps you could attach a part to the camera (make the part copy the cameras cframe) and if the camera collides with another part, push the player back?

2 Likes

Please could you provide a script for me, Thanks

1 Like

Can’t you just offset the camera back, so even though they go near the wall, the camera won’t be close enough?

Try this in a LocalScript:

--game.StarterPlayer.StarterPlayerScripts

local camera = workspace.CurrentCamera

camera.CFrame += CFrame.Angles(0,0,-2)
--Moves the camera 2 studs back.
1 Like


It just breaks the whole camera script, I can provide the camera script.

repeat wait() until game:GetService("Players").LocalPlayer.Character ~= nil
local runService = game:GetService("RunService")
local input = game:GetService("UserInputService")
local players = game.Players

CanToggleMouse = {allowed = false; activationkey = Enum.KeyCode.F;} 
CanViewBody = true 	
Sensitivity = 0.6	
Smoothness = 0.1
FieldOfView = 70		
HeadOffset = CFrame.new(0,0.55,0) 

local cam = game.Workspace.CurrentCamera
local player = players.LocalPlayer
local m = player:GetMouse()
m.Icon = "http://www.roblox.com/asset/?id=11775486559"
local character = player.Character or player.CharacterAdded:Wait()
local human = character:WaitForChild("Humanoid")
local humanoidpart = character:WaitForChild("HumanoidRootPart")

local head = character:WaitForChild("Head")
local CamPos,TargetCamPos = cam.CoordinateFrame.p,cam.CoordinateFrame.p 
local AngleX,TargetAngleX = 0,0
local AngleY,TargetAngleY = 0,0

local running = true
local freemouse = false
local defFOV = FieldOfView

local w, a, s, d, lshift = false, false, false, false, false

game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter

local easingtime = 0.1
local walkspeeds = {
	enabled =		  false;
	walkingspeed =		16;
	backwardsspeed =	10;
	sidewaysspeed =		15;
	diagonalspeed =		16;
	runningspeed =		16;
	runningFOV=			70;
}



function updatechar()
	
	for _, v in pairs(character:GetChildren())do
		if CanViewBody then
			if v.Name == 'Head' then
				v.LocalTransparencyModifier = 1
				v.CanCollide = false
				v.face.LocalTransparencyModifier = 1
			end
		else
			if v:IsA'Part' or v:IsA'UnionOperation' or v:IsA'MeshPart' then
				v.LocalTransparencyModifier = 1
				v.CanCollide = false
			end
		end
		if v:IsA'Accessory' then
			v:FindFirstChild('Handle').LocalTransparencyModifier = 1
			v:FindFirstChild('Handle').CanCollide = false
		end
		if v:IsA'Hat' then
			v:FindFirstChild('Handle').LocalTransparencyModifier = 1
			v:FindFirstChild('Handle').CanCollide = false
		end

	end
	
end

function lerp(a, b, t)
	return a * (1-t) + (b*t)
end

input.InputChanged:connect(function(inputObject)
	
	if inputObject.UserInputType == Enum.UserInputType.MouseMovement then
		local delta = Vector2.new(inputObject.Delta.x/Sensitivity,inputObject.Delta.y/Sensitivity) * Smoothness

		local X = TargetAngleX - delta.y 
		TargetAngleX = (X >= 80 and 80) or (X <= -80 and -80) or X 
		TargetAngleY = (TargetAngleY - delta.x) %360 
	end	
	
end)

input.InputBegan:connect(function(inputObject)
	
	if inputObject.UserInputType == Enum.UserInputType.Keyboard then
		if inputObject.KeyCode == CanToggleMouse.activationkey then
			if CanToggleMouse.allowed and freemouse == false then
				freemouse = true
			else
				freemouse = false
			end
		end
	end
	
	if inputObject.UserInputType == Enum.UserInputType.Keyboard then
		if inputObject.KeyCode == Enum.KeyCode.W then
			w = true
		end
		
		if inputObject.KeyCode == Enum.KeyCode.A then
			a = true
		end
		
		if inputObject.KeyCode == Enum.KeyCode.S then
			s = true
		end
		
		if inputObject.KeyCode == Enum.KeyCode.D then
			d = true
		end
		
		if inputObject.KeyCode == Enum.KeyCode.LeftShift then
			lshift = false
		end
	end
end)input.InputEnded:connect(function(inputObject)
	if inputObject.UserInputType == Enum.UserInputType.Keyboard then
		if inputObject.KeyCode == Enum.KeyCode.W then
			w = false
		end
		
		if inputObject.KeyCode == Enum.KeyCode.A then
			a = false
		end
		
		if inputObject.KeyCode == Enum.KeyCode.S then
			s = false
		end
		
		if inputObject.KeyCode == Enum.KeyCode.D then
			d = false
		end
		
		if inputObject.KeyCode == Enum.KeyCode.LeftShift then
			lshift = false
		end
	end
end)



runService.RenderStepped:connect(function()
	 
	if running then
		updatechar()

		CamPos = CamPos + (TargetCamPos - CamPos) *0.28 
		AngleX = AngleX + (TargetAngleX - AngleX) *0.35 
		local dist = TargetAngleY - AngleY 
		dist = math.abs(dist) > 180 and dist - (dist / math.abs(dist)) * 360 or dist 
		AngleY = (AngleY + dist *0.35) %360
		cam.CameraType = Enum.CameraType.Scriptable

		cam.CoordinateFrame = CFrame.new(head.Position) 
			* CFrame.Angles(0,math.rad(AngleY),0) 
			* CFrame.Angles(math.rad(AngleX),0,0)
			* HeadOffset -- offset

		humanoidpart.CFrame=CFrame.new(humanoidpart.Position)*CFrame.Angles(0,math.rad(AngleY),0)
	else game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
	end

	if (cam.Focus.p-cam.CoordinateFrame.p).magnitude < 1 then
		running = true
	else
		running = true
		if freemouse == true then
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
		else
			game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
		end
	end
	
	if not CanToggleMouse.allowed then
		freemouse = false
	end
	
	cam.FieldOfView = FieldOfView
	
	if walkspeeds.enabled then
		if w and s then return end
		
		if w and not lshift then
			FieldOfView = lerp(FieldOfView, defFOV,easingtime)
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.walkingspeed,easingtime)
		elseif w and a then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.diagonalspeed,easingtime)
		elseif w and d then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.diagonalspeed,easingtime)
		elseif s then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.backwardsspeed,easingtime)
		elseif s and a then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.backwardsspeed - (walkspeeds.diagonalspeed - walkspeeds.backwardsspeed),easingtime)
		elseif s and d then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.backwardsspeed - (walkspeeds.diagonalspeed - walkspeeds.backwardsspeed),easingtime)
		elseif d then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.sidewaysspeed,easingtime)
		elseif a then
			human.WalkSpeed = lerp(human.WalkSpeed,walkspeeds.sidewaysspeed,easingtime)
		end	
		
		if lshift and w then
			FieldOfView = lerp(FieldOfView, walkspeeds.runningFOV,easingtime)
			human.WalkSpeed = lerp(human.WalkSpeed,human.WalkSpeed + (walkspeeds.runningspeed - human.WalkSpeed),easingtime)
		end
	end
		
end)

1 Like

And what does this do?
Is this script meant to stop the camera clipping, but doesn’t work?

1 Like

This script forces first person, Sorry for confusion, But if game, If you try and walk into a wall, the camera goes into the wall

1 Like

Force first person?

Are you not able to set the player’s MaxCameraZoomDistance to 0.5, it achieves the same thing.

2 Likes

Yes, But this script polishes it, Makes you see the player character and many other things, So thats why I dont just use MaxCameraZoomDistance

1 Like

Try putting a 1 stud thick barrier on just one wall, and see if it clips.

(Experiment)

1 Like

I have tried it before, So here is a ss


The only thing is I want optimisation to be key

Is it possible to detect if the players head is inside a wall? I want optimisation to be in key because I dont want thousands of double parts, It would lag out everything

1 Like

Having a part inside the camera could probably work.

If your camera is clipping inside the wall, then the part is inside the wall.

If that’s the case, you can use :GetTouchingParts() to see if that part is inside the wall, then probably teleport you backwards.

1 Like

I like the first option, How could I set it up (Part inside the camera)

1 Like

You need a client, server scripts and a remote, since the server cannot access the camera.

Here’s the templates:

--LocalScript

local camera = workspace.CurrentCamera

camera:GetPropertyChangedSignal("CFrame"):Connect(function()
    event:FireServer(camera.CFrame.Position)
end)
--ServerScript

game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        local part = Instance.new("Part"), character)
        part.Name = "Camera"
        part.CanCollide = false
        part.Anchored = true
        part.Size = Vector3.new(1,1,1)
    end)
end)

--This breaks when the player dies, by the way.

event.OnServerEvent:Connect(function(player,position)
    local camera = workspace[player.Name].Camera
    camera.CFrame = CFrame.new(position)
    for _,part in pairs(camera:GetTouchingParts()) do
        if part.Name == "Wall" then --optional
            print("inside wall")
        end
    end
end)

I’m continuously editing this.

1 Like

If you want to detect if the head is inside, then that’s a very simple task:

game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        character.Head:GetPropertyChangedSignal("CFrame"):Connect(function()
            for _,part in pairs(character.Head:GetTouchingParts()) do
                if part.Name == "Wall" then --optional
                    print("touching")
                end
            end
        end)
    end)
end)

If this doesn’t work, then the head isn’t touching the wall, it’s the camera clipping.

1 Like


It doesn’t seem to print anything

1 Like

You’re not even clipping through the wall, that’s why.

3 Likes

I honestly don’t know how I helped but thank you.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.