How to use GetAttributeChangedSignal?

When a player joins I set an attribute like this:

player:SetAttribute("InGame", false)

Then when the player is teleported into the arena I do:

player:SetAttribute("InGame", true)

I then have in a script:

player:GetAttributeChangedSignal("InGame"):Connect(Update)

I want the update function to be called when the “InGame” attribute value changes, but nothing happens. I think it might be to do with that i’m not changing the value I’m just overwriting the old one. Anyone have any ideas?

3 Likes

Are you connecting the listener after the SetAttribute calls? The connection has to be made before, as any SetAttribute calls made before connecting won’t cause the listener to be called.

I don’t know for sure, but this could also be the problem. You can test it with a setup like this:

local anInst = Instance.new("Part")
anInst:GetAttributeChangedSignal("TestAttr"):Connect(function()
    print("Changed!")
end)
anInst:SetAttribute("TestAttr", true)
anInst:SetAttribute("TestAttr", true)

If you get two prints, then the AttributeChangedSignal fires every time SetAttribute is called, regardless of whether the value of the attribute actually changed to a new one. If you only get one print, then the value has to be set to a different one each time for the signal to fire.

Consider using BindableEvents instead if that fits your situation better, or perhaps there’s a bug somewhere else? After all, if it’s possible for a Player to have the InGame attribute set but not actually be in game, then that sounds a lot like a bug.

5 Likes

Thanks for your help. I initially set the attribute in a player added event, so this is definitely before I add the changedAttribute event. But I also update it in a different script when the player teleports into the arena which is defineitely after the changedattribute event.

-- Inside player added event
player:SetAttribute("InGame", false)
2 Likes

This one was tricky for sure… The trick was line #2.
Passing the value didn’t seem to work but just re-reading it did.

local function Update(player)
	local newValue = player:GetAttribute("InGame")
	if newValue then
		print("Teleporting", player.Name, "to the arena")
	end
end

local player = game.Players.LocalPlayer
player:SetAttribute("InGame", false)

player:GetAttributeChangedSignal("InGame"):Connect(function()
	Update(player)
end)

-- setting it off test
player:SetAttribute("InGame", true)
2 Likes

You don’t need to GetAttribute and give the player as an argument to the function.

Edit: my bad, it isn’t working because the changed connection didn’t give us the attribute value as argument. ^^

local PlayerService = game:GetService("Players")
local Player = PlayerService.LocalPlayer

local function Update(Value)
	if Value then
		print("Value is true")
	else
		print("Value is false")
	end
end

Player:SetAttribute("InGame", false)
Player:GetAttributeChangedSignal("InGame"):Connect(Update)
task.wait(5)
Player:SetAttribute("InGame", true)
1 Like

The event won’t fire if the attribute’s value isn’t changed, i.e; setting an attribute that is already true to true. To bypass this you could simply toggle the attribute’s value from false to true.

local function makeAttributeTrue(instance)
    instance:SetAttribute("Attribute", false)
    instance:SetAttrubute("Attribute", true)
end

makeAttributeTrue(part)

I want you to take that script and test it in the editor. You’ll will get nothing printed.
“Passing the value didn’t seem to work but just re-reading it did.”
If I’m going to post a full script like this, I know it needs to be tested first.

2 Likes

Oh yeah, your right! ^^
I though that this connection gave us the attribute value as argument but it don’t, my bad.

local PlayerService = game:GetService("Players")
local Player = PlayerService.LocalPlayer

local function Update()
	if Player:GetAttribute("InGame") == true then
		print("Value is true")
	elseif Player:GetAttribute("InGame") == false then
		print("Value is false")
	end
end

Player:SetAttribute("InGame", false)
Player:GetAttributeChangedSignal("InGame"):Connect(Update)
task.wait(5)
Player:SetAttribute("InGame", true)
1 Like

Thank you everyone for your help, I ended up fixing it by doing this:


-- Inside a player added function

-- As forummer said i realised i needed to change the value otherwise it wouldn't detect it.
player:SetAttribute("InGame", true)
	
player:GetAttributeChangedSignal("InGame"):Connect(function()
	updateResetButton:FireClient(player)
end)
	
player:SetAttribute("InGame", false)

-- In local sctipt
local sGui = game:GetService("StarterGui")
local player = game:GetService("Players").LocalPlayer
local RS = game:GetService("ReplicatedStorage")

local updateDonateButton = RS:FindFirstChild("UpdateResetButton")

updateDonateButton.OnClientEvent:Connect(function()
	local newValue = player:GetAttribute("InGame")
	local newState = false
	if newValue == true then
		newState = false
	else
		newState = true
	end

	repeat 
		local success = pcall(function() 
			sGui:SetCore("ResetButtonCallback", newState) 
		end)
		task.wait(1)
	until success
end)

Threw me for a loop also … you would think how you did it would work.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.