How to detect terrain water with read voxels?

(Sorry for my english i’m using a translator)

Hello, i have a script that makes screen get blurry when it’s underwater it works pretty well… if terrain.WaveSize == 0 because this script uses:

local parts = workspace:GetPartBoundsInBox(Camera.CFrame, Vector3.new())

if #parts > 0 and parts[1].Name == "Water" then
	
	-- Blurs the screen
end

I searched other methods to do this and people say to use raycast and other things but i tried all of them and none worked (probably because i made it wrong), but they don’t look like the right way to do this.

The only one that looks the right way to do this is terrain:ReadVoxels but i don’t know how to use it, i searched here but i couldn’t understand.

Every body that asked how to use read voxels in dev forum gave up because there was another solution for their problem.

I took the idea from this topic and made the following code:

local function OnRenderStepped()
	
	local Region = Region3.new(Camera.CFrame.Position, Camera.CFrame.Position + Vector3.new(1, 1, 1))
	local ExpandedRegion = Region:ExpandToGrid(4)
	
	local material, occupancy = workspace.Terrain:ReadVoxels(ExpandedRegion, 4)

	material = material[Camera.CFrame.Position.X][Camera.CFrame.Position.Y][Camera.CFrame.Position.Z]
	
	if material == Enum.Material.Water then
		
		print("a")
	end
end

game:GetService("RunService").Stepped:Connect(OnRenderStepped)

it didn’t works and the output prints “attempt to index nil with number” (line 14).

So, how should i use terrain:ReadVoxels()? Please include code samples if possible, thanks for reading.

The error means you’ve tried to reference something that doesn’t exist. Usually happens if you try to use a variable or parameter that hasn’t been set properly.

What does line 14 of your code say? It looks like the code you’ve provided is an excerpt rather than the full script.

Actually, it is the full script

the debounces are from the old script.

Try changing line 14 to this

local material = material[1][1][1]
4 Likes

Oh sorry for the late answer, it works but the hit box in the camera is really big, i tried making

material = material[0.1][0.1][0.1]

but

image

That’s because the array will not contain an index of 0.1
I think you’re misunderstanding what is actually being returned by ReadVoxels

If you print out the value of material

local material, occupancy = workspace.Terrain:ReadVoxels(ExpandedRegion, 4)
print(material)

You should see in the output something that looks like this

 {
    [1] =  ▼  {
       [1] =  ▼  {
          [1] = Air
       }
    },
    ["Size"] = 1, 1, 1
 }

If you wish to change volume of voxels that you’re reading, you will need to change the region size.

Oh sorry i’m sleepy, my fault, but now i changed the region size and the output prints “a” but the camera isn’t underwater

Maybe it’s because the wobblyness of the water. Change wavesize to 0. Then try the thing again. This won’t allow water waves. But what you can do is check humanoid state HumanoidStateType