I'm trying to achieve a glitch effect on text where letters are constantly and quickly changing to random letters/numbers/symbols, but I'm not sure how to efficiently do this.
I was thinking of creating a table of stuff like
local letters = {"a", "A", "b", "B", "!", "L"} --etc
and then using math.random to pick a random letter/symbol/number from that table and copy pasting that to create a random string about 20 characters long,
string.Text = letters[math.random(1, #letters)]..letters[math.random(1, #letters)]..letters[math.random(1, #letters)]..letters[math.random(1, #letters)]..letters[math.random(1, #letters)]..letters[math.random(1, #letters)] --etc
but I feel like this method is really inefficient and would cause bad client lag. Is there any other way to make text change constantly (in a loop) to random letters/numbers/symbols very quickly (like 0.05 seconds) and for it to be optimised? Thanks
You want to be careful with a problem like this. Strings in Lua are incredibly fast -- but not without sacrificing memory. Lua actually caches every unique string while the program is running (this is where the speed benefit comes from), therefore every new concatenation of a string is held in memory. For example, a .. b
and b .. a
would be considered two unique strings and they would both be cached (assuming that a ~= b
).
This is because strings are treated as objects in Lua. If you create the same string twice, for example, letter = "A"
and char = "A"
, both variables just become references to "A" in memory.
This is also why you can't change strings in Lua. Once you create a string, that's it! Set in stone. You can only create new strings that are modified versions of other strings.
Usually this isn't an issue, and you shouldn't have to worry about this. However, in circumstances where this concatenation is occurring in a tight or continuous loop, this is crucial to know. Due to the fact that Lua is caching every new unique string that's created, your program will eventually start to throttle if this is not accounted for.
Imagine a scenario where your program is generating 10000 unique string codes:
generate_codes(10000) --> hW81kam173 --> LkkJw93j_l8M --> 10Kau30fcm9 --> ...
This means your program is allocating memory for each one of those string objects. Yikes.
A popular solution is to store the individual characters in a temporary table, then join them together with table.concat
-- this will avoid caching the string in Lua. Here's an example:
local function randString(len) local chars = {} for i = 1, len do chars[i] = string.char(math.random(33, 126)) end return table.concat(chars) end print(randString(5)) --> WkK2_
Now, depending on your desired outcome, you may require a different version of this solution. This function will take an integer (the length of the randomly generated string) and return a string with random characters that is length long.
The randomness of the string comes from picking a number between 33 and 126 (ASCII codes) and converting that code into a character by using string.char
On the other hand, you may want to define a character set to pick random characters from instead of choosing between all the characters from 33-126. In this case, you could just pass an array and apply the same logic:
local function randString(len, charSet) local chars = {} for i = 1, len do chars[i] = charSet[math.random(#charSet)] end return table.concat(chars) end local charSet = {"a", "b", "c", "!"} print(randString(5, charSet)) --> cbb!a
It's your preference. You could also create some hybrid of the two by returning random characters from 33-126 if no character set is given, or choose characters in a defined set when one is given. I'll leave that for you to do if you're interested (or you could post another question about it if you want some help!)
For the second solution, I would recommend defining your character set early on in your code instead of passing a new table with the same characters every single time. For example...
local charSet = {"a", "b", "c", "!"} -- ... -- ... -- ... local function randString(len, charSet) local chars = {} for i = 1, len do chars[i] = charSet[math.random(#charSet)] end return table.concat(chars) end -- repeating use of `charSet` print(randString(5, charSet)) --> cbb!a print(randString(5, charSet)) --> ba!!c print(randString(5, charSet)) --> baca print(randString(5, charSet)) --> c!baa
Let me know if you have any questions!