Im making a procedural generation system, and now I am adding rivers. To do that:
I divide the river into straight segments.
For each segment, I get the corners of a bounding box with the dimensions Vector3.new(riverWidth, riverWidth, segmentLength) and it’s cframe at CFrame.lookAt(point1:Lerp(point2, 0.5), point2). (This part works)
The problem comes when I try to change the materials in the radius with water.
For that, i transform the points to the local space of a CFrame whose position is the Vector3 point1 and is looking to the Vector3 point2. If the distance in the axis X and Y is less than riverWidth/2, then I swap the material with water. (I mantain the last ocupancy).
When calling Terrain:WriteVoxels(), if the material in the 3d array is water, it looks something like this:
When using Terrain:WriteVoxels() to fill a river with water a thin layer of the original terrain (like grass) sometimes shows on top! Solids work fine, but water looks “glitched”…
Why it happens: Roblox Terrain treats water differently: its semi-transparent and layered… If there’s still solid terrain in the voxel water wont fully replace it, leaving a thin sheet of the old material…
Fixes:
Clear first: Set the voxel to Enum.Material.Air before writing water
Increase thickness: Make your river at least 2–3 voxels tall
Use FillBlock: For straight segments, terrain:FillBlock(cframe, size, Enum.Material.Water) replaces terrain cleanly without leftover layers
Always fully overwrite or clear voxels when writing water to avoid visual artifacts!!!
I will try the first 2 fixes, but since I made the river be cylindrical and then cutted by the half (not the horizontal half but the diagonal one based on the sides edges), would be hard to implement the material replacement only using Fill with basic shapes.