Raycast completely ignores water

I’m making antiexploits atm and ran into a super annoying issue with raycasting. It completely refuses to pick up any sort of water and mistakes me for “flying” in my testing place while swimming in water. IgnoreWater is disabled (by default). I can’t send my entire code here but these are the parameters and the actual raycast itself:

local RaycastParameters = RaycastParams.new()
RaycastParameters.FilterType = Enum.RaycastFilterType.Blacklist
RaycastParameters.FilterDescendantsInstances = {character}

local characterPosition = character:GetPrimaryPartCFrame().Position
local floorRaycast = workspace:Raycast(characterPosition, characterPosition - Vector3.new(0, 10, 0), RaycastParameters)

Tried everything that popped up on other posts about the same issue. Currently my only other option is creating a Region3 around their HumanoidRootPart and reading the voxels, and then detecting if it’s water. I don’t want to go out of my way to do implement this, and would rather find a way for raycasts to work as intended. Doesn’t seem particularly efficient either to create a Region3 considering this is in a .Stepped connection, not 100% sure on this though.

Humanoid:GetState() is not an option here because it’s replicated by the client, and in this instance I’m dealing with exploiters and not regular players.

Couldn’t you just do

RaycastParams.IgnoreWater = false

IgnoreWater is set to false by default, making that line unnecessary.

Is it though?, since if there is a default it would be said on the API Reference and yet there is no mention of default.

But maybe you could do a more hacky way by just putting a part above the water and detect the part from the Raycast.

It’s not officially documented but printing RaycastParams.IgnoreWater without setting it returns false. Setting it to false in the code also results in the system taking action for swimming.

1 Like

Shouldnt the direction just be straight downwards?

Why add the character position to the direction?

Also even if this doesn’t fix it, the issue I believe is that it’s like raycasting inside a part, so it doesn’t detect anything.

Otherwise try visualizing the ray as a part and see what it hits and doesn’t hit.

Subtraction, not addition. Either way, you are right. The characterPosition being subtracted from the directional vector is redundant.

Let me give the part thing a try, I didn’t think of that.

local player	= game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = character:GetDescendants()

	local origin = workspace.CurrentCamera.CFrame.Position
	local result = workspace:Raycast(origin, -Vector3.new(0, 10, 0), params)

Seems the cast direction is already relative to the start position of the raycast, this seems to be your issue.

This is what the Raycast looks like visualized as a part, everything looks correct.

Also, you were right. Not only was the characterPosition subtraction completely unnecessary, it also made the raycast go in the wrong direction. Unfortunately the water ignoring issue still isn’t fixed though.

Upon some further investigation, it seems like it works only when the character is above the water. The same applies to your code. As soon as the camera/character actually enters the water it starts to get ignored.

You can try reading terrain voxels close to the character instead of raycasting and you can see if they’re in the water. A bit performance heavy however.

That’s my backup plan if there is no way to solve the raycasting issue. “Performance heavy” is my main concern.

Raycast only returns the physical geometry of the surface. The moment that ray goes below the surface you are never getting a reading unless you hit the surface below the water.

Edit: So using Terrain:ReadVoxels and getting Material[1][1][1] should be good. I utilize this to figure out if my character is drowning.