How would one tell if a player is under water?

I was testing, and I am so sorry, I realized none of the methods work, I thought that you could do

workspace:GetPartsInPart(Terrain)

but I was wrong, I have a better alternative that I think should work better than get touching parts

1 Like

Made in a rush, but this should work fine

local Terrain = workspace:WaitForChild("Terrain");
local delay = 1;

game.Players.PlayerAdded:Connect(function(player) --A player got added
	player.CharacterAdded:Connect(function(char) --A character was added
		coroutine.wrap(function() --Wrapping for the loop
			while char do --While the character is a valid one
				task.wait(delay); --Wait the delay so it doesn't crash

				local cframe, size = char:GetBoundingBox(); 
				local materials = Terrain:ReadVoxels(Region3.new(cframe.Position - size/2, cframe.Position + size/2), 4);
				
				local redundance;
				redundance = function(t)
					if(type(t) == "table") then
						for _, m in pairs(t) do
							return redundance(m);
						end;
					else return t end; --if it is a material then it will return
				end;
				
				for _, m in pairs(materials) do --Loop in materials
					if(redundance(m) == Enum.Material.Water) then
						print("Yey"); --This is the code to execute when it is water
						break; --Breaks so that it doesn't loop more than once
					end;
				end;
			end;
		end)();
	end);
end);
1 Like

@Attyuo2 I hope the comments are enough to explain.

The reason I use redundancy is that the amount of tables depends on the resolution you give, this code is able to adapt to any resolution so if you put 1 or 10 it should still work

1 Like

Thank you all for your help, but I think I’ve found a method that best suits what I am doing! I will be using the Running Humanoid event. Thank you for your responses!

1 Like

I am happy you found a solution, just be sure to check that there is nothing that pushes the player near the water (like a car), because if there is then the .Running wouldn’t fire, and they could glitch through the water