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.
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).
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)
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)
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)