This is needed because using WorldToCellPreferEmpty or WorldToCellPreferSolid is not accurate enough to tell if your head is underwater or not.
If you stand on a shoreline it might say you’re underwater, if you swim in the sea it might say you’re above water.
This issue really makes it difficult to tell if a player is underwater or not.
P.S using Humanoid.Swimming is not accurate enough.
I don’t really understand how Humanoid.Swimming isn’t precise enough for you, but I guess you could try this…
local function terrainCast(origin,direction)
local ignoreList = {}
for _,v in pairs(workspace:GetChildren()) do
if v ~= workspace.Terrain then
table.insert(ignoreList,v)
end
end
local r = Ray.new(origin,direction)
return workspace:FindPartOnRayWithIgnoreList(r,ignoreList)
end
local function isUnderWater(humanoid)
local char = humanoid.Parent
if char then
local head = char:FindFirstChild("Head")
if head then
local hit,pos,norm,mat = terrainCast(head.Position + Vector3.new(0,1000,0),Vector3.new(0,-1000,0))
if hit and mat == Enum.Material.Water then
return true
end
end
end
return false
end
local function terrainCast(origin,direction)
local ignoreList = {}
for _,v in pairs(workspace:GetChildren()) do
if v ~= workspace.Terrain then
table.insert(ignoreList,v)
end
end
local r = Ray.new(origin,direction)
return workspace:FindPartOnRayWithIgnoreList(r,ignoreList)
end
local function isUnderWater(humanoid)
local char = humanoid.Parent
if char then
local head = char:FindFirstChild("Head")
if head then
local _,ceilingPos = terrainCast(head.Position,Vector3.new(0,1000,0))
local hit,pos,norm,mat = terrainCast(ceilingPos,Vector3.new(0,-1000,0))
if hit and mat == Enum.Material.Water then
return true
end
end
end
return false
end
It would work, if u change -1000 to the distance from head to ceilingpos.
But it would be VERY laggy, given you have to ask this atleast 2 times per second.
The method I use now works, but it’s not very good. But its more efficient than this.
I still think IsInWater is a crucial function that many more than just me uses.
A person whos head is above water doesnt drown.
Using the current terrain functions he will.
I need to check this often because you get hurt once per second ur underwater once u run out of air.
If you jump once on the water surface then this check might miss it unless it goes atleast twice per second.
For me it’s just a Y axis check to determine underwater state as all my water is flat.
This seems like a solid feature request, as we run into this issue with checking if parts are on fire or not too.
Right now the standard way to dynamically do this is a raycast to grab material and/or a cell check, although this is pretty expensive and not too accurate in many cases.