"Unable to cast double to Vector3" in custom "Invisicam"

I was trying to make a custom “invisicam” camera occlusion system so that it can be modified in game and not be Studio only.
The way I thought of it is to have a raycast from the camera to the player so that it makes the found parts transparency by their local modifier

--server script

local invisiEvent = game:GetService("ReplicatedStorage").InvisicamEvent

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.IgnoreWater = true

invisiEvent.OnServerEvent:Connect(function(plr, pos)
	local char = plr.Character or plr.CharacterAdded:Wait()
	if char then
		local rootPart = char:WaitForChild("HumanoidRootPart")
		rayParams.FilterDescendantsInstances = {char}
		local ray = workspace:Raycast(pos.Position, (rootPart.Position - pos.Position).Magnitude, rayParams)
		if ray then
			invisiEvent:FireClient(plr, ray.Instance)
		end
	end
end)

--local script

local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local rootPart: BasePart = char:WaitForChild("HumanoidRootPart")

local cam = workspace.CurrentCamera
cam.CameraType = Enum.CameraType.Scriptable
cam.FieldOfView = 25

local invisiEvent = game:GetService("ReplicatedStorage").InvisicamEvent

local rs = game:GetService("RunService")

rs.RenderStepped:Connect(function(dt)
	invisiEvent:FireServer(cam.CFrame)
end)

invisiEvent.OnClientEvent:Connect(function(part)
	if part then
		part.LocalTransparencyModifier = 0.5
	end
end)

problem is that at the local ray = line it gives me error “Unable to cast double to Vector3”. I’ve tried changing stuff but it doesnt work and doesnt even give an error. How can I fix it?

Remove .Magnitude. You want the ray to start at the camera and end at the player, so you correctly found the difference between their respective positions, but then you decided to use Magnitude which gives you the distance between the camera and the player as a scalar aka a number, but you need a vector.

If you look at the documentation for workspace.Raycast then you’ll see that the direction of a ray is a vector, not a number. This is what the output is telling you – workspace:Raycast(origin, direction, params) expects direction to be a Vector3, but instead you gave it a number which is represented in Lua(u) using the double data type. Lua(u) cannot cast (convert) a number to a Vector3 in this case, so it throws an error telling you exactly that.

Off topic, but if you’re wondering what a double is, it’s like a float but it takes up double the amount of memory. “Float” is short for “floating point number” which is any number that has a decimal (the “point”). In Lua(u), all numbers are treated as doubles, which is why the error mentions a double.

Also, why are you raycasting on the server when the result of the raycast is only used to update the client side? You can remove invisiEvent and all of the server code you provided and just perform the raycast on the client and directly change the transparency of the occluded parts. That way you’re not spending bandwidth firing the server every frame just to have the server fire back at the client with information that the client already knows. If you’re handling ALL player cameras this way with a single remote, then invisiEvent runs the risk of getting throttled from firing to too many clients at once (unless it’s an unreliable remote event, then it won’t throttle but it’ll still take up bandwidth).

This is all you need:

rs.RenderStepped:Connect(function(dt)
    local char = plr.Character
	if char then
        local pos = cam.CFrame
		local rootPart = char.HumanoidRootPart -- we don’t want to yield in RenderStepped
		rayParams.FilterDescendantsInstances = {char}
		local ray = workspace:Raycast(pos.Position, rootPart.Position - pos.Position, rayParams)
        local part = ray.Instance
		if ray and part then
		    part.LocalTransparencyModifier = 0.5
		end
	end
end)