Hello, I’m start learning metatables. Now, I need add yielding function to my script, but it works with integers. Is it possible to create something with metatables like:
local Integer = 3
Integer.Changed:Wait()
?
Hello, I’m start learning metatables. Now, I need add yielding function to my script, but it works with integers. Is it possible to create something with metatables like:
local Integer = 3
Integer.Changed:Wait()
?
I don’t believe there is any current function to check when a variable changes in a script except by using loops
I believe you can do:
repeat task.wait() until Integer ~= Integer
I am not 100% sure about this because I personally have never detected a change like linked up with a function but I think you can use __newindex(table, index, value) not sure. (just what I found when I looked around on google for the answer)
Okay, it is possible but you won’t be able to just make an int like
local Integer = 3
it would look more like:
local module = require(game.ReplicatedStorage.NumbersModule)
local Integer = module.new(3)
And you won’t be able to use .Changed
but :Changed()
instead (sorry only way I know)
Then in the ReplicatedStorage.NumbersModule
module script you would need something like this:
local module = {}
module.__index = module
function module.new(val)
local newVar = {}
setmetatable(newVar, module)
newVar.Value = val
return newVar
end
function module:Changed()
function self:Wait()
local lastVal = self.Value
repeat wait() until self.Value ~= lastVal
end
return self
end
return module
Then to test the script:
local module = require(game.ReplicatedStorage.NumbersModule)
local Integer = module.new(3)
task.spawn(function() -- This spawns a new thread so the wait won't halt script
task.wait(5) -- Wait 10 seconds until we change the value
Integer.Value = 10 -- Change the value
end)
Integer:Changed():Wait() -- Halt script
print("It's been 5 seconds") -- This prints after the value gets changed (we changed it after 5 seconds)
So yeah. This is the pretty close to what you want, as close as I can get you. Modules are pretty cool
Actual example:
local real = {}
local proxy = setmetatable({}, {
__newindex = function(_, k, v)
print('Key "'..k..'" changed to '..v)
real[k] = v
end,
})
proxy.number1 = 10
proxy.number2 = 20
print(real.number2)
Output:
Key "number1" changed to 10
Key "number2" changed to 20
20
And implementing a signal is straightforward:
local real = {}
local event = Instance.new('BindableEvent', script)
local proxy = setmetatable({}, {
__newindex = function(_, k: any, v: any)
real[k] = v
event:Fire(k)
end,
})
event.Event:Connect(function(k: any)
print('Value changed:', k, '->', real[k])
end)
--testing
proxy.number1 = 10
proxy[Vector3.new(1, 2, 3)] = CFrame.new(1, 2, 3)
proxy['yes'] = true
proxy.number1 = 20
proxy[Vector3.new(1, 2, 3)] = nil
proxy['yes'] = false
However it is recommended to use a native-Lua signal system such as GoodSignal for this kind of purpose
made a module just for it
local module = {}
local function Value_Update(tab,k,v)
getmetatable(tab):Fire(k,v)
end
function module:CreateMeta(t : table?)
local Bind = Instance.new("BindableEvent")
return setmetatable(t or {}, {
__index = {Changed = Bind.Event},
__metatable = Bind,
__newindex = Value_Update
})
end
return module
Ok so I went searching for a solution and found this post Adding a "Changed" event to a table, similar to an instance || Easy how-to guide