Lua Notes
Lua Notes
Writing a Variable:
(Insert name here) = (value)
Types of Values:
Numbers: 1,2,10,-100,5.3,etc. Integers are whole numbers, ones with decimal points are called
floating point numbers or “floats” for short.
Strings: “hello”, “bleh”, etc.
Booleans: True or False
Functions: someFunction ()
Tables: {1,2,3,4,etc.}
Threads: coroutine.create(someFunction)
Nil: nil
(If you name two variables the same, change the case as that will make one a different one)
Example Variables:
String: quoteOfTheDay = “Don’t be a lazy coder!”
Boolean: booleanExample = true
Number: numberExample = 1.923
Nil: nilExample = nil
YOU CAN ALWAYS CHANGE VALUES STORED IN VARIABLES. Simply update the variable
by assigning a new value in a line below.
If Statements:
What are “If Statements”?
If statements are a block of code that allows the computer to check for variables and make
decisions.
Set up like this: if (condition aka variable) then → go to next line to type statement
(End keyword will it appear)
Execution of Statements:
If the condition is “truthy” or met, then it will execute. If it does not meet the condition or “falsy” it
won't execute.
It is considered truth if it is any of the variable types except for nil, 0, or false
Lexical Scope
What is Scope:
A region or context that defines what variables are accessible.
If you want a variable to be in the local scope, you add local at the start. For example to restrict
a variable to just that “if then” statement, then add local to the start. Having the local keyword
makes it a different variable.
Strings:
The String Library:
Built into the code of Lua and allows you to edit what is inside strings by using a special
keyword. So you can create a string and then later when you override the variable, you can use
the keyword to change how it is printed. So “Hello World” with the string.lower override would
make it “hello world.”
String.sub:
String.sub is used to select specific parts of previous strings. It is structured as (variable, first
character of the part you want, final character of the one you want.) Ex: (exampleString, 8, 12)
#variable name will give you the character length of the string.
Concatenation:
The operation of combining two strings together. Top do this you make a variable and set its
value to another variable (add two dots) and another variable. Ex: exampleString3 =
exampleString..exampleString2. To add a space just insert another string in between them with
a space character inside.
Escape Characters:
A character that permits the use of “illegal” characters in strings. They represent non-literal
strings and perform an action when used on a string. The \ character omits the use of the
character in a technical sense and allows it to be used as just text. The \n character moves all of
the stuff following onto a new line. The \t character adds a horizontal gap between the string.
Tables:
A table is a container used to store data in a structured and organized manner. These tables
enable iteration or the process that lets the same code repeat.
Creating & indexing a table:
To make a table it is set up is: variable = {number,number,etc.} Numbers stored in a
table like this are called an array or the interpreter reads in chronological order.
These numbers are indexed so that you can simply pull the number. Ex: exampleTbl
= {32,54,-67} → print(exampleTbl[1]). That would print 32.
Table Library:
Just like a string library, but the functions deal with tables.
Loops:
Code that repeats indefinitely or until a specific condition is met.
For Loop:
A block of code that executes a finite number of times. To create this loop type: for i = 1, (value
of the times we want it to execute.), (Optional: Add a value for the increments. If you do not, the
default is one.) do (creates a new scope)
(What you want it to do)
End
(For loops are very quick.)
Ipairs Loop:
Used for arrays that have index value pairs. How to write it: (variable) = {(integer), (etc.)}
For i, v in ipairs((table from above)) do
(What you want it to do)
end
Pairs Loop:
Used for dictionaries that have key value pairs. How to write it: (variable) = {(Key) = (value),
(Key) = (etc.)}
for k, v in pairs(variable from above.) do
(What you want it to do)
end
While Loop:
Can be used until a condition is met or indefinitely. These loops can be dangerous because
unless they are yielded they can crash the game. Yielding allows the thread of execution to
“escape” from that block of code to execute other pending tasks. To write: while (boolean set to
true to make it infinite) do
(What u want executed)
End. This will crash the studio. SO NEVER DO IT. There exists a task library that helps
schedule functions in the task scheduler. The yielding one is the task.wait function which allows
you to set a time when the executor can leave. You enter a delay (in seconds). But if you leave
it blank it will execute at the default which is about 60fps. You can make it act like a for loop if
you include a variable and change the boolean to the variable and a constraint. So i = 10
While i < 100…etc
Repeat Loop:
The same as the while loop but checks for a condition at the end of running instead of at the
beginning. To write: repeat
(What you want it to do)
Until (Constraint)
Break:
Allows the thread of execution to break out of the loop prematurely. To write you do an infinite
while loop but inside the do you add a constraint using an if then statement and then you put the
“break” keyword inside the then section.
Continue:
This keyword checks if a condition is true and if it is not, it lets the thread move onto the next
iteration of the loop.. The modulo operator is the % sign. To write it, it's a for loop with an if then
inside that reads the table that the for loop has attached. Using the modulo operator you can
make the computer divide numbers.
Comparison Operators:
Less than: <
Greater than: >
Less than or equal: <=
Greater than or equal: >=
Equal: ==
Not equal: ~=
Logical Operators:
These are used in statements to check for extra parameters. U can use parentheses to section
off the statements. These can be used inside variables as well to make some variables have
two possibilities. When choosing which to read, it will read the truthy value, or if all are falsy, the
one that is first in line. Same with all truthy.
And:
Is used to check two or more parameters before execution.
Or:
Is used to check if one of the many possible parameters was met.
Not:
This can be used to make falsy values truthy.
Functions:
A function is a block of code that performs a specific task. This block of code can have info
passed to it and it can return info back.
Creating a Function:
A parameter is a placeholder identifier. It can be used instead of a value. The argument is the
value that is passed to the function when it is called. The return keyword gives the result back to
the function and allows us to exit it. Three dots can be used when doing the function to indicate
many possible parameters.
Coroutines:
A coroutine is a block of code that can do many different tasks inside the same script. Like
some other things, there is a library of code for this thing. To access you do coroutine.(the part
of the library you want) https://create.roblox.com/docs/reference/engine/libraries/coroutine
Errors:
Compile Time Error:
An error that is thrown during the compiling of our scripts (going from lua to machine code.)
Caused by poor grammar or syntax. Examples of compile errors: loca a = 5 has a spelling
mistake in “local”. You can also forget end functions on the end of them.
Runtime Errors:
An error that is thrown during the execution of the scripts. After the compilation. Typically
caused by conditions we did not account for. For example you can forget to add a value for a
table and then try to call for the value. But nothing exists.
Logical Error:
A result from our own mistake. The code works completely fine, but the code does something
we did not expect or intend. You can use print statements to test the logicality of your code to
check in on it. You can also use breakpoints which pauses the game and lets you go back to
your code and execute it line by line.
Breakpoints:
These are created by creating the red dot next to the code number line and clicking to create it.
Then you can use the three options to skip a line, go back a line or go into the next line.
pcall() Functions:
pcall() is passed a function and executes that function. If the function errors, pcall() will return
false, otherwise it returns true.
Color 3: This allows you to use three numbers that hold the R, G, B values. A color tool
basically.
Instance: Only used to create instance objects. Basically creating a new part, explosion, or GUI.
C-Frames In Depth:
A CFrame is (position set by vector 3, a rotation set by vector 3, relative to parts) To make a
new one you do CFrame.new(V1,V2,V3) A CFrame with only one vector3 will give a cframe with
no rotation. A cframe with two vector 3s will return a cframe with a rotation towards the second
vector.
There is a similar function called CFrame.lookAt(V1,V2,V3) where the third vector 3 that defines
the UpVector that has a length of one and defines “up”. A cframe with 3 vectors 3s returns a
cframe with no rotation.
Using arithmetic to make a part look at one and move towards it. LookVector is set as 1 stud so
to move it more than one you multiply it by the amount of movement (in studs) you want. After
you can also move it more by overriding the variable and adding more using a vector 3.
CFrame.Lerp (Cframe, number) returns a Cframe between the Cframe of this function and the
Cframe being called on, and the number represents the percentage of the distance from the first
cframe to the second. Multiply it by your rotating variable to maintain any rotations done to it.
Enum in Depth:
These are set up as services that we can access to compare constants together. An example of
this is the part type enum. Enum.PartType gives you access to all the basic part shapes.
Events of Roblox and How to Connect
to Them:
Roblox is very event driven. Here is a list of events and how to connect to them.
“Touched” Event: This event listens for the player to touch it. This code for example prints the
name of the part that touches it.
“Child/ Descendant added” Event: This event listens for when an instance gains a child. If the
child gains a child, only the generation before will get the event; the original part will not. To
hear for all generations you use descendant added instead of child added. This code checks if
new parts are added. Then it uses the for loop to create the new parts. The
FindFirstChildWHichA thing basically allows the part to be added as a child of the first child.
Example of Server to Client (Same setup code just the opposite way) The task.wait is there so
that the server to client sending allows for loading in:
Remote Functions:
Basically allows the client to check with the server. Like if client has password, they send to
server to verify. Never do server check with client. Could break game.
Instance Streaming:
This basically allows us to load things in procedurally as the client moves through the world.
This can help with loading times and memory usage. When they join the game, everything
within a certain replication radius will be loaded. The replication focus is a player property that
denotes the starting area for this radius.
Subproperties:
StreamingIntegrityMode: There are four choices. Disabling it makes the game not pause when it
loads things in. MinimumRadiusPause means that if the player leaves the minimum area of
loading in, then the game will pause. PauseOutsideLoadedArea makes it so that it pauses the
game when you leave the replication focus.
StreamingMinimumRadius and StreamingTargetRadius: The first one sets a radius where things
within this radius have the highest priority of loading i.e. will appear first. The second one is
much more relaxed at streaming in things. Below is an image representation. The red circle is
the minimum radius, the blue circle the target radius and the black dot is the player.
Make sure that your target radius is at least always double of your minimum radius to reduce
the amount of times the game has to pause.
StreamOutBehaviour: Basically determines when the game loads out instances. The first one is
Low Memory which loads it out when the computer starts running out of memory. The second
one is Opportunistic which loads out things outside your target radius and reloads them when
you come back.
ModelStreamingBehavior: Non-Atomic allows all of the children of the model that are not base
parts to be streamed in immediately, while the base parts are streamed in when in range.
Atomic makes everything in the model stream in when the range is achieved. Persistent has
everything in the model stream in and stay in no matter what.
Streaming Mesh: This puts a mesh around all of your instances so that when your player walks
about of the radius, it looks like nothing is loaded out and it is still there, when in reality its fake.
Good for big maps to maintain the level of openness.
DataStoreService:
Used to store data so that when the player joins the game later their data and progress is
restored.
Ordered Data Stores:
These allow us to display certain stored data.
Raycasting:
A fundamental part of the roblox API that helps the game detect objects. This is done by
shooting a “ray” and seeing if it hits into anything. You first need an origin point from where to
shoot the ray from.
Attributes:
These allow us to customize instances with our own data.
For More info:
https://create.roblox.com/docs
Terrain Tool:
This allows us to generate terrain in our world. The first tab is the create tab which randomly
generates terrain based off of a seed. The edit tab allows us to define a region and more finely
tune the terrain.
Properties of Parts:
Located in the Properties tab of parts are all sorts of tools we can use to change parts. You can
edit the color via a slider. You can choose whether it casts a shadow or not. You can change
the material to any of the Enum materials. If you are using Plastic or Glass, you can change the
Reflectivity of it to reflect the stuff around it like a mirror. The max value is 1, with it being the
most reflective. If you go above it will break. The transparency also has a max of one and sets
how see through the part is.
Particle Emitters:
These allow you to emit particles from your part. You add the particle emitter as a child of your
part. You can select the color and even have a color gradient. Light Emission blends the
particle's colors with the colors behind it. Basically, it's better to play around with it and see for
yourself.
Surface Appearances:
Go to https://polyhaven.com for the maps. U need Normal, Diffuse, Roughness, and Bump
Attachments:
Basically a small thing inside the part that can be used for particle emitters, lighting and sounds.
The attachment can move independently of the part, so you can choose where these emanate
from, instead of it coming from the center of the part.
Highlights:
This creates a white border around the part that can be seen through other objects.
SurfaceGUIs, BillboardGUIs,
ScreenGUIs:
For screen GUI, you can use the anchor point to set the location of the GUI. The bottom value
goes first (the up and down line) and the sideways one goes second. Surface GUIs go on the
surface of the part. Billboard GUIs are floating GUIs that follow the player.
Collision Groups:
These allow you to set what things can collide with what. So start them, go to the model tab and
click collision groups. Create the group names and assign the part by clicking them in the
workspace and putting them into the group. These can also be assigned through scripts.
Lighting Service:
This lets us control the lighting in our game.
Trails:
You need two attachments for this to work. Set them where you want the start and end of the
trail to be, and then select each attachment inside the trail.
Beams:
This allows us to create atmosphere in our game by basically making illusions. These beams
have to be attached to two attachments to work. You can create very cool things with them.
Clouds:
To make clouds you create a cloud as a child of the terrain. It can also be edited with scripts.
Proximity Prompts:
You can put them inside the part itself or attach them to attachments. You can also change a
property that allows it to appear only in the line of sight.
This applies force to the object taking mass and density into account.
When using a vector force, to perfectly counteract gravity, you enter a value that is the gravity
number times the mass number. This gives you a zero gravity part. Root Parts, or the parts that
don't move cannot be set. Instead they are determined by factors that increase the probability.
Anchored parts are always the root part. Parts with Massless set to false take a higher
precedence. Then parts with higher RootPriority take the next precedence. Finally, precedence
is taken by the parts size or specific names.