Get size of terrain

I need to get the size of my terrain at run-time. I can’t manually set it because the terrain is user-made, Does anybody know any way to do this?
I’ve already tried:

> terrain.Size --returns the same thing every time (2044, 252, 2044) regardless of map
> terrain.ExtentsSize --same as [terrain.Size]
> terrain.MaxExtents.Max / terrain.MaxExtents.Min --returns (-32000, -32000, -32000) and (32000, 32000, 32000) everytime

Appreciate all help.

Could you possible create a remoteevent, such that every time the player on the client side creates terrain, we send that data to the server side and update it?

1 Like

It is possible to do it whenever they place something, but my doubt here is what happens when they erase it. In order to do that, I’d need to create kind of like a “terrain tagging” system, which records which pieces of terrain cause which changes in offset.


Not sure if this explains it. Your solution would work, but maybe there’s an easier way to do it. Thanks a lot for the suggestion though.

1 Like

Why do you need the size?
Are you sure you can’t just load it across the entire world?

I need the size for saving the build to the datastore. Roblox has a pretty low limit for terrain.ReadVoxels, so I’m using an octree to divide the 3d space into acceptable sizes. However, in order to make the octree, I need the size.

1 Like

How about updating stored data whenever the player changes something, instead of reading it when saving?

1 Like

That’s an option. However, writing the terrain as a set of place/erase transactions would be insanely inefficient (both for storage space, loading times, saving times…). Anyways, I’ve found a solution already by using raycasting. It’s not the most accurate, but it’ll do. I’ll post it here once I make it a bit more usable.

This is what worked for me:

local startPosition = Vector3.new(0, 200, 0)
local downRayDirection = Vector3.new(0, -1, 0)
local upRayDirection = Vector3.new(0, 1, 0)
local stepSize = 64
local directions = {
	Vector3.new(1, 0, 0),
	Vector3.new(-1, 0, 0),
	Vector3.new(0, 0, 1),
	Vector3.new(0, 0, -1)
}

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {workspace.Terrain}
raycastParams.IgnoreWater = false


local sizeXP = 0
local sizeZP = 0
local sizeXN = 0
local sizeZN = 0
local heightP = 0
local heightN = 0

for i, dir in ipairs(directions) do
	local position = startPosition
	local size = 0

	while true do
		local downRayResults = workspace:Raycast(position, downRayDirection * 1000, raycastParams)

		if downRayResults and downRayResults.Instance then
			size = size + stepSize
			heightP = math.max(downRayResults.Position.Y, heightP)
			local upRayResults = workspace:Raycast(position - Vector3.new(0, 400, 0), upRayDirection * 1000, raycastParams)
			if upRayResults then
				heightN = math.min(upRayResults.Position.Y, heightN)
			end
			position = position + dir * stepSize
		else
			break
		end
	end

	if dir == Vector3.new(1, 0, 0) then
		sizeXP = size
	elseif dir == Vector3.new(-1, 0, 0) then
		sizeXN = -size
	elseif dir == Vector3.new(0, 0, 1) then
		sizeZP = size
	elseif dir == Vector3.new(0, 0, -1) then
		sizeZN = -size
	end
end

print("Size in XP direction:", sizeXP)
print("Size in ZP direction:", sizeZP)
print("Size in XN direction:", sizeXN)
print("Size in ZN direction:", sizeZN)
print("Size in YP direction:", heightP)
print("Size in YN direction:", heightN)

print("Size in X direction:", sizeXP + math.abs(sizeXN))
print("Size in Y direction:", heightP + math.abs(heightN))
print("Size in Z direction:", sizeZP + math.abs(sizeZN))

Keep in mind it can be inaccurate up to stepSize. The height is also only check 200 studs above/below startPosition.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.