How to prevent Leaning from making the camera clip into the walls

I’m making leaning camera system (when you hold down Q/E you lean left or right respecively) using Humanoid CameraOffset, I have had difficulties with the camera clipping through walls, I will provide my attempt at a solution below.

Code

This is the main leaning function.

local function Lean(Direction: string, Toggle: boolean)
	print("Leaning ".. Direction)
	
	
	if Direction == "Left" then
		Raycast = workspace:Raycast(Character.Head.Position, LeftCastAttachment.Position, RaycastParam)
	elseif Direction == "Right" then
		Raycast = workspace:Raycast(Character.Head.Position, RightCastAttachment.Position, RaycastParam)
	end

	
	if Raycast and not Raycast.Instance:IsA("BasePart") or Raycast == nil then
		if Toggle then
			if Direction == "Left" then
				
				LeaningDirection = "Left"

				LeanTween = TweenService:Create(Humanoid, CameraTweenInfo, {CameraOffset = Vector3.new(LeanLeftOffset, Humanoid.CameraOffset.Y, Humanoid.CameraOffset.Z)})

				LeanTween:Play()
				
				RaycastConnection = RunService.Heartbeat:Connect(UpdateLeanCast)

			elseif Direction == "Right" then

				LeaningDirection = "Right"

				LeanTween = TweenService:Create(Humanoid, CameraTweenInfo, {CameraOffset = Vector3.new(LeanRightOffset, Humanoid.CameraOffset.Y, Humanoid.CameraOffset.Z)})

				LeanTween:Play()
			end
		else
			if Direction == "Left" then

				LeaningDirection = "None"
				LeanTween = TweenService:Create(Humanoid, CameraTweenInfo, {CameraOffset = Vector3.new(0, Humanoid.CameraOffset.Y, Humanoid.CameraOffset.Z)})

				LeanTween:Play()
			elseif Direction == "Right" then
				LeaningDirection = "None"
				LeanTween = TweenService:Create(Humanoid, CameraTweenInfo, {CameraOffset = Vector3.new(0, Humanoid.CameraOffset.Y, Humanoid.CameraOffset.Z)})

				LeanTween:Play()
			end
		end
	else
		warn("LeanBlocked")
	end
	
	
		
	
end

This is the function I made to attempt to prevent clipping if the player moves into a wall

local function UpdateLeanCast()
	
	print(LeaningDirection)
	if LeaningDirection == "Left" then
		Raycast = workspace:Raycast(Character.Head.Position, Camera.CFrame.LookVector*2, RaycastParam)
	elseif LeaningDirection == "Right" then
		Raycast = workspace:Raycast(Character.Head.Position, Camera.CFrame.LookVector*2, RaycastParam)
		print(Raycast)
	elseif LeaningDirection == "None" then
		warn("Not Leaning")
		RaycastConnection:Disconnect()
	end
	
	
	if Raycast ~= nil then
		LeaningDirection = "None"
		
		LeanTween = TweenService:Create(Humanoid, CameraTweenInfo, {CameraOffset = Vector3.new(0, Humanoid.CameraOffset.Y, Humanoid.CameraOffset.Z)})

		LeanTween:Play()
		
		RaycastConnection:Disconnect()
	end
end

Video of the issue (ignore the music :melting_face:)

2 Likes

maybe instead of tweening, you could use CFrame:Lerp(), and raycast every single interpolation to see if there’s a wall in the way?

The script uses the humanoid’s CameraOffset at the moment, I’ll try this if I find that I just can’t fix this issue whilst still using it.

1 Like

Hello!

Raycast = workspace:Raycast(Character.Head.Position, Camera.CFrame.LookVector*2, RaycastParam)

You’re raycasting to Camera.CFrame.LookVector (Forward from camera)
You need to use Camera.CFrame.RightVector
And also *2 is too small

1 Like

And if I want to flip the side the cast comes from I just flip it to a negative value right?

Yes. Like this

Camera.CFrame.RightVector*-5
1 Like

wouldn’t 2 be enough? 2 studs is small but it’s not that small (unless it’s not in studs, then i’ve been living in lies all my coding life)

2 studs is this:
image
Maybe i’m blind but i’m sure that LeanOffset is bigger

1 Like

This seems to work? But it has some weird behaviour with the right hand side lean, it still clips and becomes a toggle for some reason?

The lean offset is 2.5±, I made the cast size multiplied by 2

You’re not connecting RaycastConnection if direction is Right

Oh now I feel stupid, it works fine now. Thanks man your solution was a godsend I was lost :rofl:

Nice. Then can you mark topic as solved please?

1 Like