Using attachments, how would I keep a Part in the same relative place?

If I have a Part (Part A) and another Part (Part B) parented to an Attachment that is then parented to Part A, How would I keep the relative position of Part B the same no matter what happens to the size of Part A?

For example, if Part B is positioned close to the edge of Part A and then Part A’s size changes, Part B’s position would then update to be set to close to the edge of the new size.

Is this possible? Thank you.

1 Like

You should be able to calculate the desired position of part B as follows:

partAOldSize = partA.Size
partA:GetPropertyChangedSignal("Size"):Connect(function()
    partANewSize = partA.Size

    scale = partANewSize / partAOldSize

    relativeScale = partA.CFrame:VectorToWorldSpace(scale)

    newPartBPosition = (partB.Position - partA.Position) * relativeScale + partA.Position

    partB.CFrame = partB.CFrame - partB.Position + newPartBPosition

    partAOldSize = partANewSize
end)

That should make it so the position of the attachment scales relatively to part A. If you’d like to have a part stay the same distance from the edge of part A, you could add an attachment to the edge of A then add an attachment to that attachment that has the displacement from the edge (by add attachment you might need to add a part with the attachments).

1 Like

This works somewhat, but if Part A is consistently spinning then it kind of falls apart, the parts stop lining up and end up drifting away after enough position updates.

Am I using the code correctly? It didn’t seem to work when I was using the attachment

local partA = script.Parent
local partB = partA.Attachment.Partb
local partAOldSize = partA.Size

local function onChange()
	local partANewSize = partA.Size

	local scale = partANewSize / partAOldSize

	local relativeScale = partA.CFrame:VectorToWorldSpace(scale)

	local newPartBPosition = (partB.Position - partA.Position) * relativeScale + partA.Position

	partB.CFrame = partB.CFrame - partB.Position + newPartBPosition

	partAOldSize = partANewSize
end


partA:GetPropertyChangedSignal("Size"):Connect(function()
	onChange()
end)

image

I apologise if I am doing something wrong.

Also would it be possible to change the code so if the position of PartA changes PartB updates to the same position as well? To give the illusion of moving with PartA. I can do it already but I was wondering if there was an easier way.

Oh, that’s an oversight of mine. First, it doesn’t update when the part moves. Second, the size is being stored every frame so the imprecision of the numbers being stored builds up every time.

Please try this code instead:

local RunService = game:GetService("RunService")

local partA = ...
local partB = ...

-- The values used to calculate the position of B are stored once, so no precision can build up over many times setting the position of B
local originalPartASize = partA.Size
local originalOffset = partA.CFrame:ToObjectSpace(partB.CFrame)

RunService.RenderStepped:Connect(function()
    -- Calculate the position of the part if there were no scale changes
    local unscaledPartBCFrame = partA.CFrame * originalOffset

    -- Calculate the desired position based on the overal scale change
    local scale = partA.Size / originalPartASize
    local relativeScale = partA.CFrame:VectorToWorldSpace(scale)
    local newPartBPosition = (unscaledPartBCFrame.Position - partA.Position) * relativeScale + partA.Position

    -- Replace the position with the newly calculated position
    local scaledPartBCFrame = unscaledPartBCFrame - unscaledPartBCFrame.Position + newPartBPosition

    -- Set the CFrame of partB to the calculated one
    partB.CFrame = scaledPartBCFrame
end)
1 Like

This works! But I have another problem (I’m so sorry for asking you constantly instead of just trying myself, I’ve been trying to figure this out on my own for like over a week and I just cant be bothered anymore… lol)

If PartA is spinning, it messes up the movement of the PartB(s), and if the size of the Part changes on the Y axis, it offsets the position of the PartB(s)

Medal_wFsl8FbHUr

Medal_Bk7mmT95Gm

Would it be possible to fix this?