Does GetAttributeChangedSignal() work for detecting if its children get changed?

I want to detect if an instance’s children get changed. It is a folder named “Tower” that gets changed when a timer runs out. I have tried using Changed(), but it doesn’t work. I’m wondering if GetAttributeChangedSignal() would work for it.

This is what I tried doing but got an error:

game.Workspace.Tower:Changed(function()
	wait(1)
end)

If there is any other way to detect the change then please reply!

4 Likes

Changed is not a method, but rather, an event.

game.Workspace.Tower.Changed:Connect(function()
	wait(1)
end)
2 Likes

Something like this might work:

function setup_descendant_changed_listener(ancestor, callback)
    l
    local descendant_added_c
    
    local function setup_changed_listener(child)
        local changed_c = child.Changed:Connect(function(...)
            callback(child, ...)
        end)
        local ancestry_changed_c

        ancestry_changed_c = child.AncestryChanged:Connect(function()
            if not child:IsDescendantOf(ancestor) then
                ancestry_changed_c:Disconnect()
                if changed_c.Connected then
                   changed_c:Disconnect()
                end
            end
        end)
    end
    
    --Setup for existing descendants and any that are added later
    descendant_added_c = ancestor.DescendantAdded:Connect(setup_changed_listener)
    for _, d in pairs(ancestor:GetDescendants()) do
        setup_changed_listener(d)
    end
end

setup_descendant_changed_listener(game.Workspace.Tower, function(changed_child)
    print( ("%s was changed!"):format(changed_child.Name) )
end)

Can’t test it right now but let me know if it has problems

It works all right but since there are lots of descendants of the children of the folder, (there are models inside the folder, and the models and a lot more descendants.) I would make it look for just children that are changed/added.

2 Likes

I see, here’s a version that only listens for children changed events:

function setup_child_changed_listener(parent, callback)
	local changed_cs = {}

	local function setup_changed_listener(child)
		local changed_c = child.Changed:Connect(function(...)
			callback(child, ...)
		end)
		table.insert(changed_cs, changed_c)

		--Stop listening for Changed events if the child gets a different Parent
		local ancestry_changed_c
		ancestry_changed_c = child.AncestryChanged:Connect(function()
			if not child.Parent == parent then
				ancestry_changed_c:Disconnect()
				if changed_c.Connected then
					changed_c:Disconnect()
				end
			end
		end)
	end

	--Setup for existing children and any that are added later
	local child_added_c = parent.DescendantAdded:Connect(setup_changed_listener)
	for _, d in pairs(parent:GetDescendants()) do
		setup_changed_listener(d)
	end

	--Return a cleanup function that disconnects the callback from any Changed events
	return function()
		child_added_c:Disconnect() --Don't connect callback to any Changed event for future added children
		--Stop listening for Changed events for current children
		for _, c in pairs(changed_cs) do
			if c.Connected then
				c:Disconnect()
			end
		end
	end
end

It also returns a cleanup function so you can stop listening to these events again. Here’s a test script I used:

local cleanup
cleanup = setup_child_changed_listener(game.Workspace.Part, function(child, ...)
	print(child, ...)
	if child.Name == "Stop" then
		unbind()
	end
end)

It prints every time a child of workspace.A changes, but if a child is renamed to “Stop” (or if something called “Stop” is added as a child), it stops printing.