Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Is there a way to have any variable have a 'Changed' event?

Asked by
alibix123 175
7 years ago

Something like:

x = "something"

x.Changed:connect(function(newValue)
    -- do stuff
end)
0
Nope User#11440 120 — 7y

2 answers

Log in to vote
5
Answered by 7 years ago

No

Lua tracks variables as pointing to values, and as a result you can't really check to see if you changed a variable in a Roblox-style event connection (Which is handled internally by Roblox)


Maybe.

On the other hand, it is technically possible. How you're doing it depends on the context of your script, but let's get a few important things out there:

While loops

You can technically use a while loop to check if a variable was changed, but it will only work between script iterations so be aware of this limitation:

spawn(function()
local last = varYouWantedToTrack;
while true do
  wait()
  if varYouWantedToTrack ~= last then
    -- It changed. How nice.
  end
  last = varYouWantedToTrack;
end
end);

Global variables

Global variables can be tracked using metamethods on the function environment. This is hacky and I wouldn't really particularly encourage it, because global variables are unpredictable and slower than local variables.

local connectChanged do
  local clist = {};
  local _env = getfenv();
  local mt = {
   __index = _env;
   __newindex = function(t,k,v)
     if clist[k] then clist[k](v) end;
     _env[k] = v;
   end;
  };
  setfenv(1, setmetatable({},mt));
  connectChanged = function(v,f)
    clist[v] = f;
  end;
end;

-- Example:
connectChanged('x', print)
x = 3 --> Output: 3

Callbacks

Because you're changing the variable, it's not completely unreasonable to just call a function yourself after you change it. After all, it's not hard to stick a simple callback() after you change the variable.

0
This is the closest we ever gone with changing a variable SoftlockedUnderZero 668 — 4y
Ad
Log in to vote
2
Answered by 7 years ago

This is a script made by ScriptGuider as I needed to do the same thing.

All credit to ScriptGuider.

--[[
    ScriptGuider 

    -- About --

    According to your question, you want to detect when a variable
    changes in your script. 

    All that's involved in doing so is simply storing your initial
    variables in a control table, and using a proxy to change them.
    Obviously this will involve using metatables as well, so you
    can monitor these changes using __newindex.

]]

-- Control table
local refs = {}

-- Proxy
local vars = setmetatable({},{ -- Create the proxy metatable
    __newindex = function(t,k,v)
        local rv = refs[k] -- Get the key from the refs table
        if rv and rv ~= v then -- If it exists, and doesn't equal it's old value, then...
            print("Changed: " .. tostring(k) .. " to: " .. tostring(v)) -- Whatever happens next.
        end
        refs[k] = v -- Update the value.
    end,
    -- Index function to get the values from the control table
    __index = function(t,k)
        return refs[k]
    end
})

-- Changing the variable
vars.x = 1 -- Sets the value, and nothing happens
vars.x = 2 -- Also sets the variable, but a change was detected.

--[[
    If you don't want to reference the table each time you changed a variable,
    you could modify your global environment using setfenv that uses a metatable
    to automatically interact with the vars table. Obviously this wouldn't work
    with local variables however, since they're stored differently and will not
    invoke the __newindex or __index metamethods. Here's an example:
]]

setfenv(1,setmetatable({},{
    __index = function(t,k)
        return vars[k] or getfenv()[k]
    end,
    __newindex = function(t,k,v)
        vars[k] = v
    end
}))

x = 1 -- Sets the variable, no change happens.
x = 2 -- Sets an existing keys with a different value, a change now happens.
0
Could you also provide a link to the initial post? User#11440 120 — 7y
0
Could this be converted into a bindable event using http://wiki.roblox.com/index.php?title=RBXScriptSignal? alibix123 175 — 7y
0
This was not done on any of the posts it was something ScriptGuider helped me with on the chat, I was going to make a post but ScriptGuider did not want me too. User#5423 17 — 7y
0
alibix123 this cannot be turned into an event but you could use a module script? but i dont know your game design so i cannos suggest how you should use this. User#5423 17 — 7y
View all comments (2 more)
0
wouldnt line 51 cause C Stack overflow? SoftlockedUnderZero 668 — 4y
0
test it User#5423 17 — 4y

Answer this question