It’s more that each VM instruction is 32 bits [llimits.h], they use 6 for the opcode and need three arguments, so that’s 26 bits between 3 arguments [lopcodes.h] and arguments need to be able to refer to a local by number.
So it’d take a lot of effort for ROBLOX to change.
I’m not doing anything wrong except(perhaps in your opinion) not using modulescripts. I don’t use them because I haven’t needed to. Everything is clean and non-repetitive. There is such a thing as a game requiring lots of code - this is one.
I just don’t see the point of modulescripts client-side(for this game). I can find everything pretty good. It would be nice server-side, but nearly all functions use variables in the main scope, and I don’t know how to work with that without getting hacky.
Just do what assembly programmers do. They have a limited number of registers (which are like global variables) and if they need more than 32 (or 64, or however many the architecture supports) they push unused values into memory (which in lua would probably be represented by a big table in which things get added to and removed from the back).Then, when you need those values again, you just pop them off the “stack” of memory and into your variables.
Yeah I may just have to have a local table to hold all my variables. I can and have removed a few local variables that weren’t truly necessary, but I am going to inevitably reach the limit again.
“I haven’t needed to.” - Until now.
“Everything is clean and non-repetitive” - Excellent
“There is such a thing as a game requiring lots of code” - Yes, and they use modules to help organize that code.
I can understand not wanting to go and refactor your code at this point in order to modularize it, it’s a lot of work that will probably break things and it doesn’t add any value to the game from the player perspective. But I will encourage you to see this as a learning experience so when you’re planning your next game you consider using modules.
Im organized, so I just dont get why I need modules. I use them where necessary. Its just a personal preference. If I could easily do it and make it 100% seamless with little time investment, I’d do it. It definitely is a nifty feature, just too late to implement atm. Modules wouldnt get rid of the 200 limit anyway, only delay it.
You keep using the word “organized,” I do not think it means what you think it means.
Organization and modularity go hand-in-hand with Lua. If you don’t want to use ModuleScripts, this pattern can help:
local ExposedFunction; do
local somePrivateVariable = 1
function ExposedFunction()
somePrivateVariable = 5
end
end
do blocks might sound ugly to you, but their whole point is grouping statements into manageable chunks of logic. From there, you can structure your code to properly separate responsibilities and make things maintainable. It’s a hell of a lot more efficient than performing a table lookup whenever you need to access a variable.
Organized as in I have no problem quickly locating what I want. I remember all the variable names. I don’t see the purpose of changing this particular clientside code into modulescript stuff. Modulescripts are your preference, it doesn’t make my way of doing it somehow better.
Wow, lots going on in this thread. I agree with the points about: putting it into a table; refactoring; modulizing.
One trick I’ve learned the hard way is to make sure that my variables are only within the scope of which they are needed. If I have a local variable in my “global” scope and its only used in a single function, then that can obviously be moved into the function itself.
Another tip is to possibly implement some functional programming techniques so that functions are stateless and thus data is simply passed around and returned. That might be a pain to implement into an existing code-base of yours though.
Not sure what you mean by stateless, but yeah I went back and got rid of a few variables I thought I would need globally. I reduced it by 15 or so. So I’m about one completely new feature or two away from running into the limit again
Stateless simply means that they can exist by themselves and are entirely independent of the rest of the code. In other words, the only variables it accesses comes from either itself or its arguments. It never accesses things outside of its scope (no “upvalues” as I think Lua calls them?).
Oh that’s the official term? Yeah that sounds like it would be great to have, very easy to move around. But what if I want it to access a variable rather than a value?
My problem is I have too many variables that I’d like to keep in the global scope. That’s because they are accessed more than once(or many times) in the script. If I can put them into modules, I could just put the variables inside the function and then no more problem.
In the case of functional programming in Lua, you’d just have to return the changed values and such. Can’t pass around references/pointers in Lua (except for objects/tables). C# has the nice capability of out and ref parameters.
A misconception that I see several times in this thread is that scoping using do…end somehow gets around the local variable limit. It does not. The only way to get around the local variable limit and still use local variables is to move them into functions.
And yeah, this limit is not easy for us to change since it requires extending the bytecode to 8b/insn instead of 4b, and changing the insn encoding along with serialized format.
If you don’t want to use module scripts, you could still break up the code into “objects” using tables - that would migrate a lot of functions into “methods” etc.
A function that does not affect anything outside of it’s own scope is called a “pure function”, functions that change global state are considered to have “side effects” and it is largely considered a bad practice though not everyone agrees. I find pure functions keep my code cleaner, easier to understand and makes paralleling (multi-threading) much safer since you don’t have to worry about multiple execution paths trying to manipulate the same global variables at the same time or wrap locks around everything.
Using a table called something like Global (or _global or _Global) and keeping your game state in that is perfectly acceptable and not unlike patterns I see in lots of applications. Pretty much every application has a global state it has to maintain, using global variables in a very large application gets messy quick and can cause all kinds of multi-threading issues, and some environments don’t even provide a global scope (and loaded libraries don’t have access to the global scope anyway), so creating a “global” data collection that can be passed around is sometimes the only reasonable answer.
It also makes unit testing much, much easier though that’s a different discussion.