:GetPropertyChangedSignal() Inconsistent on Attachments

Title says it all. :GetPropertyChangedSignal() has some unexpected behaviour when connecting to (seemingly) any property other than “CFrame”.

Properties I’ve tested, which do not fire:

  1. “Position”
  2. “WorldPosition”
  3. “WorldCFrame”
  4. “Orientation”
  5. “WorldOrientation”

Connecting to the event returned by calling Attachment:GetPropertyChangedSignal() with any of those properties as the parameter, simply does not fire when they change. The only one I can appear to get to work is “CFrame”. Which, is fine for my use case. However, This won’t fire when the world space properties change, only any of the local space position/rotation properties do.

This seems like a bug to me, however let me know if I should swap this into a feature request instead.

Repro code
local part = Instance.new("Part")
part.Anchored = true
part.Parent = workspace


local attachment = Instance.new("Attachment")
attachment.Parent = part

attachment:GetPropertyChangedSignal("CFrame"):Connect(function()
	print("CFrame property has changed")
end)

attachment:GetPropertyChangedSignal("Position"):Connect(function()
	print("Position property has changed")
end)

attachment:GetPropertyChangedSignal("WorldCFrame"):Connect(function()
	print("WorldCFrame property has changed")
end)

wait(1)
attachment.Position = attachment.Position + Vector3.new(0,1,0) -- line #11 will fire. Line #15 will not.
wait(1)
part.CFrame = part.CFrame + Vector3.new(0,1,0) -- nothing will fire. Expected behaviour is line #19 to fire, as the attachment's WorldCFrame has changed (among other properties)
1 Like

This is intentional. CFrame properties, their subsets (position, orientation, etc), and other properties that get updated by physics (e.g. Velocity) do not fire changed events because they change so often.

They will fire changed events if the properties are updated through Lua, but not by physics. If you need to check these properties and/or overwrite them whenever they change, you should poll the value (e.g. through RunService.Stepped) instead of using Changed events.

3 Likes

WIth that being said, shouldn’t all 3 connections in the repro be firing? The properties are being set through Lua, albeit the last property is being set indirectly through the BasePart.

3 Likes

I encountered the same problem today.

The following code snippet is made to build a hitbox so that users can “click” on a constraint.

local A0: Attachment, A1:Attachment = self:GetA0(), self:GetA1() --Getting attachments, they can be nil but in my real code I made the verification. Consider them as not nil.

local hitbox: Part = Instance.new("Part") --The hitbox part
        
--Changing a few properties
hitbox.Anchored = true
hitbox.Transparency = 1
hitbox.Name = "Hitbox"
       
--Function to update the CFrame's position, orientation & size
local function upd()
    hitbox.CFrame = CFrame.lookAt((A0.WorldPosition + A1.WorldPosition)/2, A1.WorldPosition)
    hitbox.Size = Vector3.new(.5, .5, (A1.WorldPosition - A0.WorldPosition).Magnitude + .5)
end
       
--Setup a few other systemic properties
hitbox.Parent = self.Instance
self.Hitbox = hitbox
  
upd()

--Those two events never fire.  I modified their properties on server-side (which is the context this snippet is running on), using studio tools: nothing to do, does not work.
self.Connections.HitboxPosition1 = A0:GetPropertyChangedSignal("WorldPosition"):Connect(upd)
self.Connections.HitboxPosition2 = A1:GetPropertyChangedSignal("WorldPosition"):Connect(upd)
   
--Final systemic setup
self:SetHitboxStateEnabled(true)

It looks like the error was not patched.