Raycasting help

(Original problem has been resolved, new problem now)

I’ve got a custom shiftlock script, all it does is locks the camera to 8 studs away from the head, and locks the mouse to the middle of the screen.

The problem with this is that I can look through objects, so I decided just to raycast between the head and the camera to detect if there is objects, and if there is then put the camera distance shorter just enough to not see through objects.

Seems easy enough in practice, but I discovered that if the camera is inside an object then it would not detect that object. I have no clue how to fix this, so I come here asking for help. - Solved by kexy123, solution below

Now the new problem, even though the camera zoom is being changed, I can still see inside the object, I think I can fix this using the normal of the raycast result (Basically the opposite direction from where the raycast hit), by pushing the camera in the vector of the normal, in turn pushing it away from the object.

The problem with this is I have no clue how, so help is appreciated.

2 Likes

Raycast from the character’s head position to the camera position instead of camera to character head?

2 Likes

You can Raycast from the player’s head facing towards the camera, making sure to ignore see-through parts and the character itself. Then, in that RaycastResult, You can find the distance using RaycastResult.Distance. Then, move the Camera accordingly by the distance.

1 Like

It’s not detecting if it’s at too much of an angle, pretty much only if it’s straight up or down.

And here is the script I’m testing with.

while true do
	task.wait()
	local player = game.Players.LocalPlayer
	local character = player.Character
	local head = character:WaitForChild("Head")
	local camera = workspace.CurrentCamera

	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {character, camera}
	params.FilterType = Enum.RaycastFilterType.Exclude
	local raycastResult = workspace:Raycast(head.Position, (camera.CFrame.Position - head.Position).Unit, params)

	if raycastResult then
		print("Hit an object:", raycastResult.Instance.Name)
		print("Hit position:", raycastResult.Position)
	else
		print("No hit!")
	end

end
2 Likes

Wait I think its because of the .Unit, not sure why I added that.

2 Likes

You have to increase the Unit by multiplying it by a number, in which that number is the distance. Because the Ray is only casting 1 stud away, it doesn’t detect that there’s a part and so it says it was not hit.

You should do this:

local distance = 5 -- Change this to the distance
local raycastResult = workspace:Raycast(head.Position, (camera.CFrame.Position - head.Position).Unit * distance, params)
2 Likes

And is the distance variable supposed to be the cameras distance? Or just a random number

1 Like

You can set it to however you want. Make it a constant value though to avoid any issues.

1 Like

Why would I not just get rid of the .Unit

1 Like

You can, but it’s not recommended to do so.

1 Like

Okay but why don’t you recommend it?

1 Like

You can use .unit to convert the Vector into another Vector that points at that same direction but only with a Unit of 1. So you can multiply this by a distance that you can edit.

TL;DR: It’s unpractical to not use it.

1 Like

WRONG > (Okay well I just discovered this isn’t gonna work because for some reason the minimum CameraMaxZoomDistance is 8, so I cannot change that based on the distance of the object and the head.) < WRONG

After thinking logically for 5 seconds, I realised that it was illogical to be able to change the maximum zoom below the minimum zoom.

1 Like

Okay, now a new problem has occurred that I don’t know how to fix.

While yes, the camera will not let me look far into an object, I can still clip the camera slightly into the object making it invisible. To fix this I think I need to move the camera forward slightly, the problem is Idk how to do that.

I believe this is the calculation I would use to move the camera, but I have no experience moving the camera or doing any of this really.

local direction = ((raycastResult.Position - camera.CFrame.Position).Unit * 5)

1 Like

You can find the distance of the RaycastResult, then subtract it by an amount so that the camera is not clipping through an object.

local distance = RaycastResult.Distance - 0.5

Then, we move the camera away by that distance.

Camera.CFrame = CFrame.new(Head.Position) * Camera.CFrame * CFrame.new(-distance, 0, 0)

I’m not really sure if CFrame.new has the correct values.

1 Like

Workspace.AntiNukeYT.Player.LocalScript:16: attempt to perform arithmetic (unm) on nil

1 Like

That only happens if the Raycast did not find an object to hit. Wrap both the distance and the camera changing lines in an if statement if the Raycast did hit something. If it didn’t just set the camera normally.

1 Like

Okay sure this moves the camera forward, but I wanna make it move away from the object its hitting

Edit : I’m not sure this is even working, still doing testing.

Edit 2 : This is not working, it does nothing.

1 Like

I don’t understand. Could you clarify the question, please?

1 Like

This is the issue.

As you can see, even though the camera distance changing IS working, you can still see through the floor.

As a solution, I wanted to just shoot the camera forward a slight bit so it’s not “inside” the wall, so it does not become transparent. Now that I’m thinking of it, I remember some variable being the direction the object is facing. Perhaps we could just move the camera in that direction.

1 Like