This new method returns a version of the Instance.Changed signal that is will be fired for just one property.
The idea behind this is that it’s sometimes needlessly expensive to listen to the Changed signal for all properties when you only care about a few properties or just one property. Using this API a filtered version of the signal can be used to listen to only those properties.
local function OnCameraChanged(property)
if property == 'CameraSubject' then
-- Do CameraSubject specific stuff here
end
end
The issue with code like this is that it makes other Camera properties a lot more expensive to update, especially busy properties like CFrame. The CFrame property for the Camera can be updated twice per frame (once for the camera update and then once for the occlusion update) and for each of these updates there are around six Changed signal listeners in the CameraScripts and PlayerScripts that need to be fired. This is made worse by the fact that the update also needs to fire the Changed signal with the legacy CoordinateFrame property.
With the new GetPropertyChangedSignal API expensive listeners like the above code can be replaced with the following:
workspace.CurrentCamera:GetPropertyChangedSignal("CameraSubject"):connect(function()
-- Code that deals with CameraSubject update here
end)
Would it be possible for some behaviour regarding GetPropertyChangedSignal to be changed (heh)?
Currently, .Changed doesn’t fire for certain busy properties such as Position of parts (unless manually set, of course). This is undesirable in cases where I do in fact want to listen to Position changes of the part. If I explicitly fetch the signal for the Position property changing, I want to be able to listen to that rather than needing to poll with a while loop. GetPropertyChangedSignal on Position doesn’t fire when Position is changed (it functions like regular .Changed where it only fires if manually set).
This is the code I used to test it out:
script.Parent.Changed:connect(function(property)
if property == "Position" then
print("generic changed")
end
end)
script.Parent:GetPropertyChangedSignal("Position"):connect(function()
print("GetPropertyChangedSignal changed")
end)
script.Parent.Position = Vector3.new(0, 50, 0)
EDIT:
Not suggesting .Changed should fire every frame the physics engine/position updates, asking that :GetPropertyChangedSignal would explicitly fire every frame the physics engine/position updates. If I explicitly call for the signal of a property, then I want to know explicitly when it changes.
This would go for any similar property that doesn’t seem to fire with .Changed as it changes via physics engine or whatever.
I assume this was initially done as an optimization, though it might be feasible to pull back if the developer can now pinpoint the property they want to listen to.
Might as well just poll using Heartbeat loop. I would listen for Position change, then hook up Heartbeat loop until position change is at some minimum change, then kill the Heartbeat connection.
Anyway, this is cool. Quick question: If you call GetPropertyChangedSignal("Name") three times, will it return 3 separate signal instances, or the same one?
This would be nice because you are explicitly asking for the property changes with GetPropertyChangedSignal but I don’t think it’s practical to implement unfortunately. I think there would be an overhead associated with checking if the developer has explicitly asked for changes for these properties that would make it too expensive to do for all moving parts every physics step.
The internal signal used will be the same but the object returned to Lua will be different (this is also what happens when you index an Instance to get a RBXScriptSignal). Comparison will work as expected because the comparison checks the contents of the RBXScriptSignal rather than if the actual object is the same.
Yeah, that was the primary reason why I opted for the signal method to fire when these busy properties change.
It does seem in hindsight now more reasonable to have an event fire on sleeping, this would allow a simulation of the changed event for these sorts of busy properties (ie connecting/disconnecting on wake/sleep; I believe Position, Rotation, and CFrame are all busy properties that do wake-up the part/keep it awake regardless).
Could you allow us to connect to locked properties as some locked properties have functions to get their value ( PGS, loadstring via pcall, etc ). .Changed allows this so I’m not sure why this shouldn’t.
In play solo, things like loadstringenabled can be changed which I’d like to track for my admin that allows a loadstring command when it’s enabled. Another use I can think of is needing to change how certain things operate depending on whether or not PGS is enabled, and as it can be set in play solo would be useful to be able to track when it changes as its value can be gotten.