I’m trying to read a region of terrain and copy it over to somewhere else in the game: (original on the right, copied version on the left)
And whilst this is mostly working, it isn’t perfect - in some places the terrain is not perfectly copied over, in these two images for example:
The way the script works is that it reads one region, takes the materials & occupancies and applies that to another region.
The reason that I think is is something to do with Roblox instead of me is because once given the materials and occupancies, I’m never changing it, but once applied the values seem to have changed.
I also do a check within the script to confirm that they’ve changed, comparing the original material and occupany values to the new ones (gained from reading this new region). The script also shows that both values are not the same.
Some other things:
- Both regions are the same size
- Both regions are the same orientation (different position, ofcourse)
- Both regions fit within the region size boundary
- Region covers all the terrain
Here is also the script I used if necessary: (the only script in the whole game)
Script
--// Services
local Terrain = workspace.Terrain
--// Variables
local region1Part = workspace.Region1
local region2Part = workspace.Region2
--// Constants
local RESOLUTION = 4
--// Functions
local function roundVector3(vector, toNearest)
return Vector3.new(
math.round(vector.X / toNearest) * toNearest,
math.round(vector.Y / toNearest) * toNearest,
math.round(vector.Z / toNearest) * toNearest
)
end
local function roundSize(part, toNearest)
part.Size = roundVector3(part.Size, RESOLUTION)
end
local function getRegionVolumeVoxels(region)
local size = region.Size
return (size.x / RESOLUTION) * (size.y / RESOLUTION) * (size.z / RESOLUTION)
end
local function isRegionTooLargeForReadWriteVoxels(region)
return getRegionVolumeVoxels(region) > 4_194_304
end
local function isRegionTooLarge(region)
return getRegionVolumeVoxels(region) > 67_108_864
end
--// Main
roundSize(region1Part, RESOLUTION)
roundSize(region2Part, RESOLUTION)
local readPos1 = roundVector3(region1Part.Position - (region1Part.Size/2), RESOLUTION)
local readPos2 = roundVector3(region1Part.Position + (region1Part.Size/2), RESOLUTION)
local readRegion = Region3.new(readPos1, readPos2)
local materials, occupancies = workspace.Terrain:ReadVoxels(readRegion, RESOLUTION)
local writePos1 = roundVector3(region2Part.Position - (region2Part.Size/2), RESOLUTION)
local writePos2 = roundVector3(region2Part.Position + (region2Part.Size/2), RESOLUTION)
local writeRegion = Region3.new(writePos1, writePos2)
workspace.Terrain:WriteVoxels(writeRegion, RESOLUTION, materials, occupancies)
--// Checks
task.wait(2)
local _materials, _occupancies = workspace.Terrain:ReadVoxels(writeRegion, RESOLUTION)
warn(materials == _materials, occupancies == _occupancies) -- Prints false false (different)
print(isRegionTooLargeForReadWriteVoxels(readRegion)) -- Within boundaries
print(isRegionTooLargeForReadWriteVoxels(writeRegion)) -- Within boundaries
P.S. I also made a #help-and-feedback:scripting-support post, but nobody knew why this was happening. (Post)