How to detect when player camera is underwater

I’ve searched every corner of the internet to no avail. I’m trying to get a script that can detect if the player camera is underwater, and will take into account waves. Using getvoxels or getcells won’t work because it doesn’t take into account waves and is not accurate.

This isn’t impossible, it has been done before.

https://www.roblox.com/games/367959224/Robloxian-Waterpark?refPageId=a5b7a08a-5bb0-4d69-845c-5c75ce690bd9

This is a great example of what I need to achieve. This game takes into account waves, and I don’t know how it works but I want to.

5 Likes

In addition, I would like for it to play a sound when it is underwater, but I can do that by myself, it just needs to be detected.

Maybe check if the animation the player is in is a swimming animation?

I’d like to politely ask you to reread my post. No where does it mention the character or animation(s).

3 Likes

In addition, I would like for it to play a sound when it is underwater, but I can do that by myself, it just needs to be detected.

just an idea, someone will probably come up with a better solution, what if u would create a part and would make a while loop in which u would be setting part.CFrame to CurrentCamera.CFrame? Then u can handle it with touched event or Regions3.

2 Likes

He meant that the way that you can detect whether the player is underwater is by checking if the swimming animation is currently being used and if its used then you can play your sound.

I believe Roblox will need to work more on the water in Roblox Studio anyways.

2 Likes

You can try raycasting at the camera origin forwarding the look vector of the camera:

local Ray = Ray.new(Camera.Position, Camera.CFrame.LookVector.Unit)
local Part, _, FloorMaterial = workspace:FindPartOnRay(Ray)
if FloorMaterial == "MaterialHere" then

end
3 Likes

Nuttela, The touched event doesn’t coagulate with waves, especially terrain.

Tamzy, His post is completely irrelevant and does not help me at all. Detecting the swimming animation does not yield the result I want.

Top, I believe raycasting only works on voxels, is there any way you could show me its accuracy?

Top, I tested out what you said and it does not work.

while wait() do
	local Ray = Ray.new(game.Workspace.CurrentCamera.CFrame.p, game.Workspace.CurrentCamera.CFrame.LookVector.Unit)
	local Part, _, FloorMaterial = workspace:FindPartOnRay(Ray)
	if FloorMaterial==Enum.Material.Water then
		print('p')
	end
end

Unfortunately that is what I explained I did not want in my post because it is inaccurate and does not take into account waves.

Maybe this will help:

https://devforum.roblox.com/t/how-to-get-wave-height-at-a-specific-position/30672/3

That seems needlessly complicated. Also, I don’t think that would take into account the game’s water wave height

That seems needlessly complicated. Also, I don’t think that would take into account the game’s water wave height

I heard roblox’s water wave clock is incremented based on the speed or something
So if the speed is 0 when you join the game it’ll be at the starting value. Then you can change the speed to the actual value and take a timestamp and then you have a close estimate on the clock which you can use to determine surface height

Maybe if you raycast from the camera focus to the camera position this would work and using the #4 value from the function:

local Camera = workspace.CurrentCamera

while wait() do
local _, _, _, Material = workspace:FindPartOnRay(Ray.new(Camera.Focus.p, Camera.CFrame.p-Camera.Focus.p))
   if Material == Enum.Material.Water then
      print("a")
   end
end
1 Like

Hey, this idea might be nuts but just know i’m trying to help. What if you make a part, add a humanoid to it and then constantly position it to where the camera is. And check if that part’s Humanoid.FloorMaterial = water and then do whatever it is you’re doing with ur script. I know…it’s crazy but that’s the way i would approach it. Let me know what you think.

1 Like

Your solution doesn’t work at all. It’s not the problem that it doesn’t function, it just doesn’t function as to detection

A combination of these two should work:
Read terrain voxels
Camera CFrame

EDIT
ReadVoxels takes in a region3 to match the terrain’s 4x4x4 grid of voxels. It will return a list of materials and occupancies. Materials define if the voxel is in any way populated by terrain. Occupancies describe the voxels geometry and how much that voxel is occupied by the material.
I assume this value can be used for better precision; but it also appears to be constant and probably won’t help with wave size.