The title speaks for itself. This module will allow you to listen for any changes made to a variable. It’s supposed to be similar to the .Changed event used for Instances and whatnot.
The module itself uses OOP, or object oriented programming.
This script is included in the module along with an additional one.
-- This script will show you how to use the module
local changedEventModule = require(script.Parent) -- Require the module
local exampleVariable = "foo bar" -- This is the variable we will want to be listening for changes.
-- We must declare a new variable for the changed event to work, and then continue off said variable. Pass exampleVariable as the argument.
local listeningVariable = changedEventModule.new(exampleVariable)
-- Now we must listen for changes via Listen() method using the new variable we declared.
listeningVariable:Listen()
-- Set up listener
local listener = listeningVariable:GetListener()
listener.Event:Connect(function(value)
print("Variable has changed! New value: "..value)
-- do stuff
end)
-- Alternatively, you can do these
-- listeningVariable:GetListener().Event:Connect(function(value)
-- listeningVariable.event.Event:Connect(function(value)
-- To change a value, you use the SetValue() method
listeningVariable:SetValue(123) --> Variable has changed!
-- listeningVariable.value = 123 --> Variable has changed!
-- To get a value, you use the GetValue() method
local var = listeningVariable:GetValue() --> 123
--local var = listeningVariable.value --> 123
-- To stop listenting for changes, you use the StopListening() method
listeningVariable:StopListening() -- The listener handler will not function until you listen for changes again.
listeningVariable:SetValue("foo bar") --> No output, because it's currently not listening for changes. The value will still change.
-- listeningVariable.value = "foo bar" --> No output ^^^^
-- Now we can listen for changes again
listeningVariable:Listen()
listeningVariable:SetValue(1234) --> Variable has changed!
If you have any suggestions or questions for me, let me know.
This little library is kind of useless for the most part, but if you need it, there’s some problems with it.
The main problem is that it polls.
Which means it’s constantly asking: “Is this value changed?”
And that’s not optimal, it’s horrible for performance, especially if you have a bunch of these around.
You can just instead, :Fire the bindable whenever the value changes, not having this problem at all.
This does it like that:
local Node = {}
Node.__index = Node
function Node.new(variable)
local self = setmetatable({
_value = variable,
_bindable = Instance.new("BindableEvent")
}, Node)
self.Changed = self._bindable.Event
return self
end
function Node:GetValue()
return self._value
end
function Node:SetValue(newValue)
if self._value == newValue then
return
end
self._value = newValue
self._bindable:Fire()
end
function Node:Destroy()
if not self._bindable then
return
end
self._value = nil
self.Changed = nil
self._bindable:Destroy()
self._bindable = nil
end
return Node
nice, only the Destroy function isnt really needed. if you make the variable in script nil the binable event will be removed automaticly since its parent is nill and its not stored by script anymore either.
This isn’t actually completely true, logically it would be, but when you mess with instances the entire thing gets messed up and garbage collection is way more of a crybaby.
Usually self-referencing references would not cause an issue to the garbage collector, however when it comes to using a BindableEvent this is a lot more problematic.
Basically the layer between Lua and C (Instances and by extension BindableEvents and RBXScriptSignals) doesn’t understand references that well, and basically if you ever reference anything that is or has a reference to that BindableEvent, it will count as a strong reference even if the only reference is a reference inside that Instance’s event connection which would usually not matter since its disconnected from the rest of the game.
Basically, referencing your bindableevent inside that bindablevent’s connection completely breaks garbage collection for that instance, and so if you want to clean that up you need to destroy the bindableevent or disconnect everything before hand in some way.
What this means is that if you reference the Node in a connection on .Changed on it, that will be a memory leak unless you destroy the Node before getting rid of its references.
The other better way is to not use a BindableEvent or any instance in general, and instead use a Lua implementation of a Signal. That way you don’t depend on weird Instance shenanigans like these.