How can I prevent first person camera from clipping into walls?

I am making a first person camera and i can’t figure out how to prevent the player’s camera from clipping into walls like this:

The piece of code responsible for the camera positioning is this:

		newCameraCFrame = newCameraCFrame.Rotation
			+ (
				(torsoCf.Position + (torsoCf.UpVector * ((torso.Size.Y / 2) + (player.Character.Head.Size.Y / 2))))
				+ (torsoCf.LookVector * (torso.Size.Z * 0.8))
			)

that’s inside PlayerModule > CameraModule > ClassicCamera, so I am editing the cframe that the default roblox camera handler gives.

1 Like

You can prevent this.

You would need to Raycast from the Players Head to check if the Part is close to your Head (or where you are facing), and set a new Offset from there.

A solution could be to make a new part every time RunService.RenderStepped is called. (You would obviously delete the old part every time it’s called as well.)
Then, you’d run part:GetTouchingParts() and see if the part is touching any parts not parented to the player character.
If a part is detected, move the part backwards until it is no longer touching that part and have the camera’s offset be re-calculated using the parts new position.

I should probably note that this method isn’t the most efficient, just the easiest to code (in my opinion).

This wouldn’t be ideal

If you are doing Parkour and about fall off a part or are climbing on a Part, This “Part” will most likely kick you off of it.

It’s not moving the camera CFrame, it’s moving the Humanoid’s CameraOffset value.
This is what you’re using, correct?

Yes, I’m not stupid, i know what CameraOffset is.

I’m saying the Part will need to be positioned in a way to Prevent Camera from Clipping, when doing specific things whilst the Part is Positions in front of the Player, It would disrupt that State.

I decided to code it myself. You may look at the results here:

As you can see, the Humanoid’s state is not disrupted. It works perfectly fine.

If you look in the camera modules, you’ll find a specific module which I don’t know if you’ve review already, called “ZoomController”. Inside that, “Popper”. That module is responsible for the clipping of the camera.

image

You can look in this module to see if anything here helps. You said in first person so the module might deactivate itself when the player is in first person. Try disabling that.

1 Like

I solved this by preventing the player from moving if a raycast from the camera hits a wall, this is inside PlayerModule > ControlModule in the :OnRenderStepped function:

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Blacklist

local function getGraphEquation(point1: Vector2, point2: Vector2)
	local slope = (point1.Y - point2.Y) / (point1.X - point2.X)
	local yIntercept = -slope * point1.X + point1.Y
	-- local function getX(y: number)
	-- 	return (y - yIntercept) / slope
	-- end
	local function getY(x: number)
		return slope * x + yIntercept
	end
	return getY
	-- return getX, getY
end

local x2 = 90 -- The point we'll use for if statment
local getY1 = getGraphEquation(Vector2.new(0, 2), Vector2.new(x2, 4))
local getY2 = getGraphEquation(Vector2.new(x2, 4), Vector2.new(180, 4))
local function getY(x)
	if x > 90 then
		return getY2(x)
	else
		return getY1(x)
	end
end

if moveVector ~= Vector3.zero then
			local angle = math.acos(math.clamp(char:GetPivot().LookVector:Dot(moveVector), -1, 1))
			local ray = workspace:Raycast(camCf.Position, moveVector * getY(math.deg(angle)), rayParams)
			if ray then moveVector = Vector3.zero end
		end

Basically what the getY function does is changes the length of the raycast direction vector depending on where the player is moving, so if they were moving forward, the vector would be 2 studs long, so if anyway exists at 2 studs in front of the player, they will stop moving, if the player was moving to the side, the vector would be 4 studs, and if they were moving backwards the vector would be 2 studs.
https://streamable.com/tt22y8

2 Likes

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