Is having a list in a table better than a bunch of variables?

So when working on a Roblox game to keep things easy I made a lot of variables so I can tweak multiple things at once very easily and I made it rather complicated, so much so that I hit the 200 variable limit :sweat_smile:, When researching this problem on solution was to use less local variables and swap them out for the global scope variables, but I also read that they can make some loops up to 10% slower, Iā€™m not using many loops, but Iā€™m using enough where this might not be a good solution in the long run. Another solution I found was to use tables to store the variable data but Iā€™m not sure if that would run into a similar problem or not and I cant seem to find much information of weather or not tables cause any performance issues or anything like that when used in place of a local variable, and so I wanted to know if anyone does know what the best solution here would be

and for those wondering what Iā€™m using 200+ local variables its to make a combat system for my AMMORPG (action mmorpg(yes I get a lot of questions about the a and yes I put a parenthetical in a parenthetical) ) and I want to take a lot more inspiration from fighting games such as Tekken, Guilty gear, Rivals of Aether, smash , Street Fighter, King Of Fighters (I just bought kof 15 its awesome), brawlhalla, and MAHVEL BABY, so that the game will be a bit more balanced than the average and have a more in depth combat system while still being accessible to players that just want numbers to go up and big explosions, of course the Iā€™m also takes inspiration from mmorpgā€™s such as Elder scrolls online, Dungeons and dragon neverwinter(I want to add dungeons that are dungeony, most roblox ā€œdungeonā€ games are very bland with no traps or treasure or dragons or puzzles or any cool secrets or strategy to complete they are just a go kill the badguys type of thing and I dont want the dungeons in my game to be like that), Guild Wars 2, BlackDesertOnline, final fantasy and runescape. of course I also take inspiration from shooters by adding GUNS, anyway the current name of the game is project:Collided (I dont know if anyone took it already lol) and I expect trailers for the game to start releasing sometime at the end of this year or this time next year, most likely with an actual name of course. (sorry for talking about my game so much lol)

I canā€™t even begin to imagine how youā€™re hitting the 200 local variable limit unless youā€™re doing something incredibly complex. There is no reason for the vast majority of developers to be hitting that limit, let alone reaching any number near it.

Smells like an XY problem: I think you need to reduce the amount of variables youā€™re creating and/or split into other scopes rather than tunnel vision yourself into resolving this through only a dichotomy of tables or variables. Poor structuring is just as much a problem and that seems like your main issue.

Declaring globals is bad practice. Not only does it not resolve your issue but it has bad practice implications as well. Besides the ones provided by Luau/Roblox, globals are in most, if not all cases, a code smell. ModuleScripts, Attributes and ValueObjects exist if you need a variable shared across multiple scripts.

I work on an ARPG. Hereā€™s a recent gameplay segment from my gameā€™s developer previews section:

Albeit having a deeply complex combat system, I have never ran into the issue of maxing out the amount of local variables I could have. Itā€™s never been a problem either considering my entire codebase is fractured off into over 2000 ModuleScripts.

What Iā€™m saying is: you need to refactor your combat system. 200 local variables should never be an issue for most developers. If you leave it be or implement a quick-fix solution, itā€™s going to become technical debt that will bite you hard later when you want to update.

1 Like

yea, the main thing taking up the variable limit is just a way to make an attack by altering variables like when the attack has movement the hitbox size, placement, if its a projectile and moves, if the attack can clash with other attacks and if so what element type is it, and if the attack has any properties like does it give super armor or hyper armor. and if its a multihit attack and a lot more, and this is all here so my brothers and anyone we hire can add weapons easily without needed to learn how to code and to easily balance weapons if they make the attack too good and im not sure how to reduce it without making it harder to use, I think I should swap to putting each attacks variables in a table, but im not sure if it would cause problems like how global variables do, I assume not so I think im gonna do that for now until someone can confirm weather or not they do cause lag

You need to write parametrised functions and start splitting up your code into ModuleScripts. Sounds like youā€™ve got a monolithic script coming on which is going to be horrible for updating.

Being anywhere close to 200 variables in one thread (including the main one) is inherently wrong and your problem isnā€™t going to resolve itself by putting them in a table. You wonā€™t see the limit warning but now you have other practice problems: additional memory consumed for the table, reading elements from the table rather than just local variables, poor readability and poor maintainability. It is not going to be easier to hire developers to make changes to something colossally cluttered.

Every step of damage calculation should be in its own script. You can create a damage instance or original damage value and run it through each function to determine if you need to apply any changes and if so what those changes are.

200 variables, whether or not you put them in a table or not, is outright bad.

1 Like

damage calculation is already done in a separate script and so is most other things I hit the 200 variable limit inside of one of my module scripts, so then should I try to split up my module script in to a few smaller module scripts?
here is an some of the variables being used for one hit of an attack

local m1_1upS = false -- weather or not vector3 movement is used during the startup frame
local m1_1upM = false -- weather or not vector3 movement is used during the multihitstart frame
local m1_1upA = false -- weather or not vector3 movement is used during the active frame
local m1_1upH = false -- weather or not vector3 movement is used during the hit frame
local m1_1upR = false -- weather or not vector3 movement is used during the recovery/endlag frame
local m1_1upSV = Vector3.new(0,3,0) -- movement
local m1_1upMV = Vector3.new(0,3,0)-- movement
local m1_1upAV = Vector3.new(0,3,0) -- movement
local m1_1upHV = Vector3.new(0,10,0) -- movement
local m1_1upRV = Vector3.new(0,10,0) -- movement
local m1_1backwardVS = false --if the velocity is goingbackward
local m1_1backwardVM = false --if the velocity is goingbackward
local m1_1backwardVA = false --if the velocity is goingbackward
local m1_1backwardVH = false --if the velocity is goingbackward
local m1_1backwardVR = false --if the velocity is goingbackward
local m1_1VHonblock = true --if the velocity on hit activates when hitting a blocking opponent
local m1_1velocityS = 0 -- forward velocity on startup (each of the velocitys need to be at least bigger than 0 so 1 or 0.1 for the upvector to take effect)
local m1_1velocityStime = 0.5 -- velocity time on startup
local m1_1velocityM = 0 -- forward velocity on active
local m1_1velocityMtime = 0.5 -- veloctity time on active
local m1_1velocityA = 0 -- forward velocity on active
local m1_1velocityAtime = 0.5 -- veloctity time on active
local m1_1velocityH = 0 -- forward velocity on hit
local m1_1velocityHtime = 0.5 -- veloctity time on hit
local m1_1velocityR = 0 -- forward velocity on recovery
local m1_1velocityRtime = 0.5 -- veloctity time on recovery
local m1_1VSstoponhit  = true -- if the velocity stops when u land a hit
local m1_1VMstoponhit  = true -- if the velocity stops when u land a hit
local m1_1VAstoponhit  = true -- if the velocity stops when u land a hit

local m1_1isagrab = false -- DO NOT USE MULTIHIT OR PROJECTILE HITBOXES FOR GRABS!, also try to keep the hitbox small if the grab animation is fast

local m1_1hitboxplacement = CFrame.new(0,1,-3) -- the hitbox placement
local m1_1hitboxmovewithplayer = false -- most useful for moves with a lot of mobility and air attacks
local m1_1hitboxsize = Vector3.new(9, 3, 6) --the size of the hitbox
local m1_1hitboxdestroyonhurt = true -- weather or not the hitbox destroys when the player takes hitstun (always use for melee attacks, optional for projectiles)

local m1_1element = "nuetral" -- the elemant type of the attack
local m1_1strength = 2 -- how strong the hitbox is colliding (NOT THE ATTACK DAMAGE, attack damage is in the serverscript)
local m1_1relfectprojectilehb = false -- weather or not the hitbox reflects projectiles

local m1_1multihit = 0 -- how many multihits the move has if any
local m1_1multihitonhit = false -- if true then the rest of the multihits wont play until the first hit lands
local m1_1multihitboxsize = Vector3.new(8, 3, 6) -- the size of the multihit hitbox size
local m1_1multihitboxplacement = CFrame.new(0,1,-3) -- the position of the multihit hitbox
local m1_1multihitprojectile = false -- if the multihit is a projetile
local m1_1multihitprojspeed = 22 --the speed of a multihit projectile and used for the multihit on hit projectile
local m1_1multihitprojlife = 1 --the life of a multihit projectile and used for the multihit on hit projectile
local m1_1multihitprojbreakonhit = true -- if the projectile breaks when hitting an opponent
local m1_1multihitprojbreakoncontact = true -- if the projectile breaks when hitting anything
local m1_1multihitprojmouseaim = true -- if the projectile shoots in the direction of the players mouse
local m1_1multihitairattack = false -- if the multihits can be anti aired
local m1_1multihitboxdestroyonhurt = true -- if the multihibox will be dstroyed on being hit

local m1_1projectile = false -- if the attack is a projectile
local m1_1projspeed = 20 -- the speed of the projectile
local m1_1projlife = 2 -- how long the projectile lasts
local m1_1projbreakonhit = true -- if the projectile breaks when hitting an opponent
local m1_1projbreakoncontact = false -- if the projectile breaks when hitting anything
local m1_1projmouseaim = true -- if the projectile shoots in the direction of the players mouse

local m1_1projectileinvincable = false -- weather or not the attack is invincable to projectile attacks
local m1_1superarmor = 0 -- how many hits of super armor the move has
local m1_1hyperarmor = false -- if the move has hyper armor
local m1_1antiair = false -- if the move is invulnrable to most air attacks
local m1_1invincable = false -- if the move makes you invincable during the startup and active frames
local m1_1hitsroll = false -- if the attack hits rolling opponens
local m1_1blockbreak = false -- if the move can block break (used here if the move cancels when hitting a blocking opponent)
local m1_1airattack = false -- if the attack loses to anti airs attacks (used for all air attacks except projectiles)

then for a few other things are done using animation markers for more specific stop and starting of some attributes like if the attack lets u move through players or your considered airborne to be immune to basic grabs and stuff like that, I dont think they matter in this scenario

also what will this game be called or where can I keep up with its news till its relesed?

You should make a ModuleScript for each attack, and load/unload them when you need to use the attack.