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
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.
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:
-and after some refining…
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.
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
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.