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

How can I properly avoid the 200 local variable limit?

Asked by 4 years ago
Edited 4 years ago

I have a module script that contains all of the functions for my gui event handler local script. This module script is now erroring because the variable limit has been surpassed. I was rather surprised when this happened, but, because it did, I needed to find a way around it. All the variable definitions are wanted and used. This is a module script that has references to most of the guis in the game, along with references to remotes, objects, and various other things, so simply using fewer variables is not going to cut it.

As always, I did some discussion and research before posting this question. There were two main solutions that people came up with. Those are what I wish to ask about. Which one is best in performance, code convention, and general code simplicity?

Option One:

Use a do end block / don't define variables locally. Now, both options are not ideal, but if they're the best, I'll definitely take them, because they're not that difficult to implement. For example, instead of defining player locally, I could do this:

player = players.LocalPlayer

or this:

do
    player = players.LocalPlayer
end

Now, I don't see a significant difference between the two (other than the second seeming worse and useless), but I'll leave it up here because it was a suggestion someone made.

Option Two:

Use a table. Now, this option makes sense, but it does mean rewriting large portions of my code, which I'd like to avoid. Not only that, but how exactly should I implement tables? Should I have a different table for each chunk of variables that deal with similar things? Should I do that, but also put each different table into one main table? Should I just put everything into one main table? Should I leave some variable definitions, but move others into tables?

I'd appreciate advice on this matter. If you have a different solution altogether, feel free to post that as well. I'm open to pretty much anything that makes sense, works, and isn't going to require a massive overhaul of the whole system (which seemed pretty smooth until I ran into this limit).

Thanks!

0
It seems the tables are your best bet, the global variable one wont be good performance wise Fad99 286 — 4y
0
How are you hitting the limit? If you don't use a variable often, for example if you have a number in a variable, and you don't use it often, you're better off using a number literal. User#24403 69 — 4y
1
In all the Lua code I have seen no one has hit this limit. If you even get close to this amount you are doing something badly wrong. User#5423 17 — 4y
0
Do note that using a well named variable instead of a number literal can help code clarity (and if it's used in more than one place, it keeps the code easy to change later). chess123mate 5873 — 4y
0
@kingdom5, I believe it is the fact that I've dedicated all client side gui functionality to this one module script, which results in a large number of variables, especially if you have several guis. User#26971 0 — 4y

1 answer

Log in to vote
1
Answered by 4 years ago
Edited 4 years ago

(Note that using non-local variables in a do end block doesn't help anything. Also, in terms of performance, local variables are slightly faster than non-local variables, and not using a table is slightly faster than using one - but the difference is very small; it's best to consider performance when working on a piece of code that (for instance) runs in a loop every frame.)

For the sake of organization, it is better to separate your script into smaller segments (ideally smaller scripts) that are each responsible for a smaller job (see https://en.wikipedia.org/wiki/Separation_of_concerns). If you can make each segment "know" as little as possible about other segments (and ideally knows about as few segments as possible), you decrease the number of dependencies for each segment. That way, if you later decide to change something, you minimize the amount of other code that you'll need to update.

To fix your problem, you could put all your variables into tables, but on its own this doesn't improve organization/separation of concerns and is also incurs a performance penalty (and a fair bit of rewriting).

Ways to help fix your problem that also help with organization:

  1. Keep it all in the same script, but divide up the parts of the script using do end and local variables. The idea is to make sure that a variable is only in scope for a section of the script - define any functions that need to use it, then end the block. The goal is to have each section of a script only deal with one main idea. If you are successful, you may find that you can move some of the blocks into different scripts entirely (although this may not be easy to do if there are a lot of variables that are accessible to the entire original that the block relies on).
  2. Improve organization even more by using ModuleScripts to store useful functionality (assigning the functions and any other values to the ModuleScript's table so that other scripts can access them, of course). If you can identify a job that your main script is doing, you may also be able to put that in its own LocalScript -- ex, maybe one of the jobs is to make buttons light up when you hover over them. If it needs to access variables from your original script, you could store those variables in a ModuleScript - perhaps your original script could become a ModuleScript that returns a table of useful variables, for instance. Alternatively, see if you can pass in information to functions rather than functions accessing the information themselves (ex, instead of a piece of code knowing to light up a specific button, turn it into a function that is told which button to light up).

Method 1, managing locals with scopes, is probably the least work and it should solve your immediate problem, though you should consider transitioning into the 2nd option over time, even if you don't want to do it all at once.

An example of method 1:

local Players = game.Players -- variable accessible to all blocks
local someGlobalVar = thatManyBlocksUse

do -- Manage a specific aspect of the GUI, ex some buttons
    local button1 = pathToButton1
    local someLabel = etc
    -- use button1/someLabel/etc
end

do -- Manage a different aspect of the GUI
    -- more local variables
    -- etc
end

-- You can also "export" functionality from a scope by defining the variable outside the 'do end':
local CountSpeciallyNamedChildren -- arbitrary piece of functionality
do
    local specialNames = {SpecialName=true, VerySpecialName=true}
    function CountSpeciallyNamedChildren(obj)
        local ch = obj:GetChildren()
        local count = 0
        for i = 1, #ch do
            if specialNames[ch[i].Name] then
                count = count + 1
            end
        end
        return count
    end
end
-- You can now access CountSpeciallyNamedChildren but specialNames is hidden and therefore doesn't count towards the variable limit. It's also clear to see where "specialNames" is used/modified, making it easier to find bugs.
Ad

Answer this question