Anyone have a good method for camera collisions?

scripting camera collisions for a custom camera has got to be the most annoying thing ive ever had to do.
camera:GetLargestCutoffDistance() works most of the time but if you’re almost parallel with a wall and your camera collides into it, the camera still clips into it some. if you simply raycast from like a player’s head to the camera’s target position and position the camera in the hit point, the camera clips into the walls still just slightly. That being said, anyone have a good method to detect camera collisions and position the camera in a suitable way where the camera doesn’t clip into parts at all? I tried looking at the default camera scripts which does a good job at achieving this but I can’t find anything.

5 Likes

You can detect collision by raycasting using this code.
Edit: This gets rid of the clipping issue btw.

local Character = game.Players.LocalPlayer.Character
local Camera = game.Workspace.CurrentCamera

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
28 Likes

You could define the HumanoidRootPart’s Position as a centre point and then grab the Camera’s Position by doing local CameraPosition = workspace.CurrentCamera.CFrame.Position and then you could cast a Ray like this: local Ray = Ray.new(Center, CameraPosition - Center) local Hit, Position, Normal = workspace:FindPartOnRay(Ray) and from there you could change the Position by adding the Normal returned and multiplying it by 0.4 which would transform in to the following: Position = Position + Normal * 0.4 and then when changing the Camera’s CFrame you can take in to account the new Position returned.

Edit: Implemented this and here are the end results: https://gyazo.com/11ac42b632fed8a1a73ba0d70b95e6a6

4 Likes

Your results are still clipping very slightly. The code I provided is 100% accurate.

2 Likes

Fixed, just needed to mess around with the multiplier a bit. https://gyazo.com/11ac42b632fed8a1a73ba0d70b95e6a6

where do you put this code? also no renderstep needed?

If you’re still looking, this will work:

local PlayerService = game:GetService("Players")
local RunService = game:GetService("RunService")


local player = PlayerService.LocalPlayer
local character = player.CharacterAdded:Wait()
local camera = game.Workspace.CurrentCamera


RunService.RenderStepped:Connect(function(deltaTime)
	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)

(Just a modification of the above answers.)

4 Likes

This script seems to break when you reset the character.

This might just work:

local PlayerService = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = PlayerService.LocalPlayer
local camera = game.Workspace.CurrentCamera

local function onCharacterAdded(character)
	camera.CameraSubject = character:WaitForChild("Head")
end

player.CharacterAdded:Connect(onCharacterAdded)

RunService.RenderStepped:Connect(function(deltaTime)
	local character = player.Character
	if not character then
		return
	end

	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)
5 Likes

Where would I put the code? Also LocalScript or Serverscript?

You can put the code in StarterPlayerScripts or StarterCharacterScripts
The script is local

The script still has slight clipping issues.

2 Likes

Bumping this because I need answers for a question, does this work for Enum.CameraType.Scriptable

Because for my game I use a custom camera for the cars and I want to add a feature where you can inspect your car inside your garage from all angles and my struggle may be camera collision through the floor.