Absolute size of a part

Well, I was wanting to get the size of a randomly rotated part falling through the sky so I could stop it right before it hits the ground. I thought there would be an easy way to do this with roblox’s built-in functions or properties but I guess I’m wrong

If a part is rotating it doesn’t mean it’s size is changing

1 Like

So essentially you are looking for the lowest point on a part, yes?

You can get each corner of a box as CFrame offsets, and then constantly check to see if the lowest Y position from the 8 corners is on the ground, and once its about to hit, simply anchor it.

Is this correct?

Yeah. Well, Ideally I could get the size in x, y, and z. But yeah that’s essentially what I want.

Well the problem is that if the part is spinning, then the offset from the ground will be different as it rotates. Will it be actively spinning or is it a static rotation as it falls?

I’m talking about relative to the world. If you change the rotation of an object, it visually looks like it’s a different size. I know this shouldn’t be too hard to find, I’m just having a hard time.

It’ll be static so you don’t need to repeatedly check. I thought Part.CFrame.Rotation * Part.Size would work to get the size relative to the world but It doesn’t seem to always work.

Are you talking about something like this?

2 Likes

Thats much easier to find out then; I was thinking it was spinning.

local function getBlockOffsets(part) -- returns a list of cframe offsets from the center of the part to each corner --
	local offsets = {}
	for i = -1,1,2 do
		for j = -1,1,2 do
			for k = -1,1,2 do
				offsets[#offsets+1] = CFrame.new(part.Size.X*.5*i, part.Size.Y*.5*j, part.Size.Z*.5*k)
			end
		end
	end
	return offsets
end

This function will return a list of 8 offsets to each corner of a part, and once you do that you can just sort by the lowest point like this:

table.sort(offsets, function(A,B)
	local cf_A = copy.CFrame * A
	local cf_B = copy.CFrame * B
	return cf_A.Y < cf_B.Y
end)

The lowest offset will be at offsets[1], and you can get the world position by:
`(part.CFrame * offset[1]).Position’

If you put your part into a model you can use GetBoundingBox which will get you results like @lmaomano12345’s post

Update; messed around in studio and made this:
lowestpointonblock
-and after some refining…
lowestpointonblock2

Here is the code I used to make it, assuming the script is inside a part:

Code

local RN = game:GetService("RunService")
local DB = game:GetService("Debris")

local block = script.Parent

local function createBlock() -- this is just to create a part, you can ignore this --
	local copy = block:Clone()
	copy:ClearAllChildren() -- removes script ;)
	copy.Size = Vector3.new(math.random(2,4), math.random(1,2), math.random(3,4))*10
	copy.CFrame = block.CFrame * CFrame.Angles((math.random()-.5)*math.pi,(math.random()-.5)*math.pi,(math.random()-.5)*math.pi) + Vector3.new(0,100,50)
	copy.AssemblyAngularVelocity = Vector3.new(math.random()-.5,math.random()-.5,math.random()-.5)*100 -- random spin --
	copy.Parent = workspace
	return copy
end

local function getBlockOffsets(part) -- returns a list of cframe offsets from the center of the part to each corner --
	local offsets = {}
	for i = -1,1,2 do
		for j = -1,1,2 do
			for k = -1,1,2 do
				offsets[#offsets+1] = CFrame.new(part.Size.X*.5*i, part.Size.Y*.5*j, part.Size.Z*.5*k)
			end
		end
	end
	return offsets
end

local part = Instance.new("Part")
part.Anchored = true
part.CanCollide = false
part.Size = Vector3.new(2,2,2)
part.Material = "Neon"
part.Parent = workspace

while true do
	task.spawn(function()
		local copy = createBlock()
		local offsets = getBlockOffsets(copy)
		local connection
		connection = RN.Heartbeat:Connect(function()
			table.sort(offsets, function(A,B)
				local cf_A = copy.CFrame * A
				local cf_B = copy.CFrame * B
				return cf_A.Y < cf_B.Y
			end)
			local dest = copy.CFrame * offsets[1]
			part.CFrame = dest
			if dest.Y < .1 and connection then
				connection:Disconnect()
				connection = nil
				copy.Anchored = true
				DB:AddItem(copy, 3)
			end
		end)
	end)
	task.wait(7)
end

Its not perfect but you can tweak it as you see fit.

Yeah, is GetBoundingBox the only easy way to do it?

yeah, I am assuming it is. credits to @gertkeno though for the answer.

It’s weird because GetBoundingBox and GetExtentsSize don’t even return accurate results half of the time. I’m so confused.

This seems to be the solution but for some weird reason it’s not working for me. How would i get parts size depending on its rotation? - #4 by nicemike40

Does that work for you? You said no, but you marked it as an answer :slight_smile:

I assumed in that post that the part is only rotated in increments of 90 degrees.

If that’s not the case for you, you’ll have to be more specific about what you want.

Do you want to find the axis-aligned bounding box of a given part?

Well, that should be exactly what I’m looking for, but sometimes somehow it doesn’t give a correct output. Like I’ll randomly rotate a part in the workspace, and measure it, but the script will tell me it’s a different height.

Sure, but what exactly is your desired output? Can you give examples of inputs and outputs?

Well, I’ll just give the example I have right now. I have a part with a size of 20, 30, 40, and an orientation of 20, 90, 150. I measured its height at around 47.5 studs, but your script outputs a Y value of around 28.7.

Here, I “borrowed” some of @zeuxcg’s code for fast AABBs, used in GetExtentsSize, and simplified it for a single part:

-- returns the size of the axis=-aligned bounding box of a given part
function GetAABB(part)
	local abs = math.abs

	local cf = part.CFrame
	local size = part.Size
	local sx, sy, sz = size.X, size.Y, size.Z

	local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = cf:components() 

	local wsx = abs(R00) * sx + abs(R01) * sy + abs(R02) * sz
	local wsy = abs(R10) * sx + abs(R11) * sy + abs(R12) * sz
	local wsz = abs(R20) * sx + abs(R21) * sy + abs(R22) * sz
	
	return Vector3.new(wsx, wsy, wsz)
end

I found zeux’s code through this post originally.

That’s slightly slower than the GetWorldSize function I originally posted (not that this level of optimization really matters), but also will work for any orientation. Not just 90 degree increments.

9 Likes