Why isn't this raycast detecting terrain water?

I am trying to make a small raycast to detect whether or not the player’s camera is in water.

However, it’s not detecting terrain at all and most of the time just outputs nil. Sometimes it detects the player’s head.

This is a local script running under Player Scripts:

while true do
	local camera = workspace.CurrentCamera
	local raycastParams = RaycastParams.new(
		Enum.RaycastFilterType.Whitelist,
		{workspace.Terrain},
		false
	)
	local raycastResult = workspace:Raycast(camera.CFrame.Position,camera.CFrame.LookVector*1,raycastParams)

	for i=1, 15 do
		print(string.rep(" ", i%2))
	end
	print(raycastResult)
	wait()
end

I don’t think the RaycastParams constructor takes any arguments. Try this instead:

local raycastParams = RaycastParams.new()

--//Assign fields directly to the new object
raycastParams.FilterDescendantsInstances = {character} --//Anything else you want the ray to ignore
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

local result = workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector, raycastParams)

if result and result.Material == Enum.Material.Water then
print("The ray hit water!")
end

Well this detects the water when the camera is above it and looking at it, however if the camera is in the water it still doesn’t detect it.

Try this:

local result = workspace:Raycast(characterModel.Head.Position, camera.CFrame.LookVector)

On second thought though, I don’t think there’s a clear shot to this. I think this has always been a caveat of raycasting where if the origin position is inside of what you’re trying to cast a ray to it doesn’t work properly. The only thing I can think of is exaggerating the origin position so it’s always above the water, then casting a ray long enough downward to still be able to hit the water. The only thing that’d need to change is we’d want to make sure the player is actually swimming or in the water, because otherwise it’ll say they’re in water when they might not truly be.

if result and result.Material == Enum.Material.Water and characterModel.Humanoid:GetState() == Enum.HumanoidStateType.Swimming then
print'blah'
end

I’m not sure how I would do that without running the risk of hitting something else before hitting the water

Try visualizing a raycast and see what the results are.

Also, for your destination point on the raycast, try doing : End - Start.