How to properly detecting camera collisions

So I’m trying to detect when a camera collides into a part and handle how it positions itself from that. I’ve been having some trouble with this problem for a while. I don’t wanna clutter everything with a bunch of unrelated stuff, so here’s the portion where I handle the collision detection (camera movement and everything works except collision detection):

local free_interval=2 --amount in can move in 1 update
run_service:BindToRenderStep('FreeCamera',Enum.RenderPriority.Camera.Value,function()
			camera.CameraType='Scriptable'
			local free_p=free_spring.position*free_interval
			local current_cframe=camera.CFrame
			local new_cframe=look_angles*cf(free_p)+current_cframe.p
			
			local hit,pos,norm=raycast(workspace,ray(current_cframe.p,new_cframe.lookVector*free_interval))
			
			camera.CFrame=not hit and new_cframe or current_cframe
		end)

My goal is to have the collisions working, and if a collision is detected, the camera still has movement in any unrestricted directions, so the camera can essentially “scrape” against a wall unless its movement is directly perpendicular to the wall. If anyone can help out here that would be great :smile: I’m almost positive I’m trying to take too much of a simplistic approach, but I’m not sure how to approach this issue.

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Camera = game.Workspace.CurrentCamera
local Ignore = {
     Character
}

local CameraRay = Ray.new(Character.HumanoidRootPart.Position, Camera.CFrame.Position - Character.HumanoidRootPart.Position)
local HitPart, HitPosition = game.Workspace:FindPartOnRayWithIgnoreList(CameraRay, Ignore)
Camera.CFrame = (Camera.CFrame - (Camera.CFrame.Position - HitPosition)) + (Character.HumanoidRootPart.Position - Camera.CFrame.Position).Unit
2 Likes

Alright, so I used that and the behavior is definitely much closer to what I’m looking for, but when I got to a wall, the camera would stutter for a bit and then phase through the wall. Any idea on how I could fix it?
this is what it looks like:
https://gyazo.com/f4721d21b8bebb5a740e28dca4c59169
For your code, I just treated the HumanoidRootPart as the original position and the camera’s position as the target position.

        local free_p=free_spring.p*free_interval
		local current_cframe=camera.CFrame
		local new_cframe=look_angles*cf(free_p)+current_cframe.p
		
		local camera_ray=ray(current_cframe.p,new_cframe.p-current_cframe.p)
		local hit,pos=raycast(workspace,camera_ray)
		
		if hit then
			camera.CFrame=(new_cframe-(new_cframe.p-pos))+(current_cframe.p-new_cframe.p).Unit
		else
			camera.CFrame=new_cframe
		end

If you want to get less wall scraping, you can consider working with position data. Imagine a (small) sphere around the camera that cannot collide with the wall. If you then cast a ray directly out of the camera and compare the size of it to the radius of the imaginary sphere you can determine if the camera can move further (ray size > r) or not (ray size <= r).

If the camera is moving at high speeds, above method could fail. Depending on the code you use, you could factor in the amount of movement of the camera per update/frame to counter this. Keep that in mind.

1 Like

I assumed something else when you said you wanted the camera to “scrape” against the surface. The code I sent isn’t going to work for your situation.

That idea would work very well for what OP is asking for
As for high speeds, simply using a

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

or

game:GetService("RunService").RenderStepped:Connect()

Would allow for quick calculations and seamless transitions.

Actually, with any active camera manipulations (e.g. Player controlling it) I would highly recommend using RenderStepped as it happens every time a frame is finished calculating.