How to stop fixed third person camera from seeing through walls?

The camera in my game keeps going through walls and allows the player to see the other side of it. Is there a way to disable this?

firearm.Equipped:Connect(function(mouse, character)
	
	-- Stop clipping through walls
	--local cameraRay = Ray.new(character.Head.Position, camera.CFrame.Position - character.Head.Position)
	--local ignore = {character}
	
	camera.CameraType = Enum.CameraType.Scriptable

	userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	
	local character = player.Character
	local humanoid = character:WaitForChild("Humanoid")
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
	
	local cameraAngleX = 0
	local cameraAngleY = 0	
	
	local function playerInput(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Change then
			cameraAngleX -= inputObject.Delta.X
			cameraAngleY = math.clamp(cameraAngleY - inputObject.Delta.Y * 0.4, -40, 40) -- Change 0.4 if needed
				
		end
	end
	contextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
	runService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value, function()
		local startCFrame = CFrame.new(humanoidRootPart.CFrame.Position) * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
		local cameraCFrame = startCFrame:PointToWorldSpace(cameraOffSet)
		local cameraFocus = startCFrame:PointToWorldSpace(Vector3.new(cameraOffSet.X, cameraOffSet.Y, -1000000))
		camera.CFrame = CFrame.lookAt(cameraCFrame, cameraFocus)
		
		
		local lookingCFrame = CFrame.lookAt(humanoidRootPart.Position, camera.CFrame:PointToWorldSpace(Vector3.new(0, 0, -100000)))
		
		
		humanoidRootPart.CFrame = CFrame.fromMatrix(humanoidRootPart.Position, lookingCFrame.XVector, humanoidRootPart.CFrame.YVector)	
		--[[
		local cameraRay = Ray.new(character.Head.Position, camera.CFrame.Position - character.Head.Position)
		local ignore = {character}
		
		local hitPart, hitPosition = game.Workspace:FindPartOnRayWithIgnoreList(cameraRay, ignore)
		camera.CFrame = (camera.CFrame - (camera.CFrame.Position - hitPosition)) + (character.Head.Position - camera.CFrame.Position).Unit
		]]
	end)
end)

You were on the right track with the Ray, but I would use Raycast. You need the Unit for the direction, and the distance to get the correct covered area.

firearm.Equipped:Connect(function(mouse, character)
	
	-- Stop clipping through walls
	--local cameraRay = Ray.new(character.Head.Position, camera.CFrame.Position - character.Head.Position)
	--local ignore = {character}
	
	camera.CameraType = Enum.CameraType.Scriptable

	userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	
	local character = player.Character
	local humanoid = character:WaitForChild("Humanoid")
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
	
	local cameraAngleX = 0
	local cameraAngleY = 0	
	
	local function playerInput(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Change then
			cameraAngleX -= inputObject.Delta.X
			cameraAngleY = math.clamp(cameraAngleY - inputObject.Delta.Y * 0.4, -40, 40) -- Change 0.4 if needed
				
		end
	end
	contextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
	runService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value, function()
		local startCFrame = CFrame.new(humanoidRootPart.CFrame.Position) * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
		local cameraCFrame = startCFrame:PointToWorldSpace(cameraOffSet)
		local cameraFocus = startCFrame:PointToWorldSpace(Vector3.new(cameraOffSet.X, cameraOffSet.Y, -1000000))
		camera.CFrame = CFrame.lookAt(cameraCFrame, cameraFocus)
		
		
		local lookingCFrame = CFrame.lookAt(humanoidRootPart.Position, camera.CFrame:PointToWorldSpace(Vector3.new(0, 0, -100000)))
		
		
		humanoidRootPart.CFrame = CFrame.fromMatrix(humanoidRootPart.Position, lookingCFrame.XVector, humanoidRootPart.CFrame.YVector)	
		
		local rayparams = RaycastParams.new()
		rayparams.FilterDescendantsInstances = {character}
		rayparams.FilterType = Enum.RaycastFilterType.Blacklist
		
		local origin = character.Head.CFrame.Position
		
		local ray = workspace:Raycast(origin, (origin - camera.CFrame.Position).Unit * (origin - camera.CFrame.Position).magnitude, rayparams)

		if ray then
			camera.CFrame = ray.Position
		end
	end)
end)

I’m getting a ā€œunable to assign property CFrame. CoordinateFrame expected, got Vector3ā€ error in this if-statement:

if ray then
    camera.CFrame = ray.Position
end

try camera.CFrame = CFrame.new(ray.Position)

1 Like

Is the code supposed to do this? O_o