In-Depth Scripting Guide: Difference between revisions

From Legacy Roblox Wiki
Jump to navigationJump to search
>Jaccob
>JulienDethurens
No edit summary
Line 17: Line 17:


Example:
Example:
<pre>
<code lua>
example = game.Workspace.Example
example = Workspace.Example
</pre>
</code>


Notice how the variable has a name, which is "example."  The name can be anything except numbers alone.  If you have a name of just numbers and you use it in a script, you will end up with a syntax error.  When defining a variable, you need to tell exactly where it is.  The Explorer tab helps with this as there is always a little tab telling you that that object is a child of something.  When typing the parental of the object you want, spell the parental(s) correctly.  You do not need the function ":FindFirstChild()" when making variables.
Notice how the variable has a name, which is "example."  The name can be anything except numbers alone.  If you have a name of just numbers and you use it in a script, you will end up with a syntax error.  When defining a variable, you need to tell exactly where it is.  The Explorer tab helps with this as there is always a little tab telling you that that object is a child of something.  When typing the parental of the object you want, spell the parental(s) correctly.  You do not need the function ":FindFirstChild()" when making variables.
Line 27: Line 27:


Example:
Example:
<pre>
<code lua>
bin = script.Parent
bin = script.Parent


Line 39: Line 39:


bin.Touched:connect(onTouched)
bin.Touched:connect(onTouched)
</pre>
</code>
There is the one variable, not really needed but I need to stress its importance.  In the first function, as in every function, the term "function" is first.  It is correct if the term turns purple.  After the term "function," the function needs to be named (in the example, there are two -- named "anchor" and "onTouched".)  Do not use numbers as a name.  It is better to spell out numbers in names, except in some occasions.  Now, after the name, you'll see the word "object" in parentheses.  You can rename it anything you want, except numbers, and you can use it for anything you want.  It's like a function variable, you can use it to do other things and use it repeatedly with different terms. You can also add more variables to this by using commas. So, this example could have been made: "function anchor(object, statement)".  In this function, though, it is anchoring the object no matter what.  Finally, the "end" statement.   
There is the one variable, not really needed but I need to stress its importance.  In the first function, as in every function, the term "function" is first.  It is correct if the term turns purple.  After the term "function," the function needs to be named (in the example, there are two -- named "anchor" and "onTouched".)  Do not use numbers as a name.  It is better to spell out numbers in names, except in some occasions.  Now, after the name, you'll see the word "object" in parentheses.  You can rename it anything you want, except numbers, and you can use it for anything you want.  It's like a function variable, you can use it to do other things and use it repeatedly with different terms. You can also add more variables to this by using commas. So, this example could have been made: "function anchor(object, statement)".  In this function, though, it is anchoring the object no matter what.  Finally, the "end" statement.   


Line 48: Line 48:


Example:
Example:
<pre>
<code lua>
bin = script.Parent
bin = script.Parent


Line 60: Line 60:


bin.Touched:connect(onTouched) --this is called the "connection line"
bin.Touched:connect(onTouched) --this is called the "connection line"
</pre>
</code>
Presuming this script is inside of a brick, it can therefore be touched.  In the variables, the brick is called "bin."  In the connection line, there is a specific order in which the line should be.  It should be like this:
Presuming this script is inside of a brick, it can therefore be touched.  In the variables, the brick is called "bin."  In the connection line, there is a specific order in which the line should be.  It should be like this:
<pre>&lt;Object&gt;.&lt;Event&gt;:connect(&lt;Function&gt;)</pre>
<pre>&lt;Object&gt;.&lt;Event&gt;:connect(&lt;Function&gt;)</pre>
Line 76: Line 76:


====Example One====
====Example One====
<pre>
<code lua>
brick = game.Workspace:findFirstChild("Brick")
brick = Workspace:findFirstChild("Brick")
if brick then
if brick then
print("The brick is here!")
print("The brick is here!")
end
end
</pre>
</code>
In this snippet of code, the brick variable is defined as whatever is given by FindFirstChild. The if statement will check if the `brick` variable is neither nil nor false. If the FindFirstChild function returned a brick, then the if statement block of code will be run.
In this snippet of code, the brick variable is defined as whatever is given by FindFirstChild. The if statement will check if the `brick` variable is neither nil nor false. If the FindFirstChild function returned a brick, then the if statement block of code will be run.


Line 87: Line 87:


====Example Two====
====Example Two====
<pre>
<code lua>
number = 0
number = 0
while number < 10 do
while number < 10 do
Line 96: Line 96:
end
end
end
end
</pre>
</code>
On the first line, "number" is 0.  The next step is a 'while true do' loop.  It waits one second then "number" will increase by one.  Then there is the 'if' statement.  It is now asking if "number" is greater than 5.  If "number" is greater than 5, it will print, "Number Greater Than 5!"  If it isn't greater than 5, then it will just skip it and repeat the loop.  Once "number" turns to 11, the loop will end.  This also goes with connection functions.
On the first line, "number" is 0.  The next step is a 'while true do' loop.  It waits one second then "number" will increase by one.  Then there is the 'if' statement.  It is now asking if "number" is greater than 5.  If "number" is greater than 5, it will print, "Number Greater Than 5!"  If it isn't greater than 5, then it will just skip it and repeat the loop.  Once "number" turns to 11, the loop will end.  This also goes with connection functions.


Line 103: Line 103:
===The 'else' Statement===
===The 'else' Statement===
Say you have an 'if' function, but it has false or nil inside. That's when the 'else' kicks in. It does the function of the else onward to the end statement.   
Say you have an 'if' function, but it has false or nil inside. That's when the 'else' kicks in. It does the function of the else onward to the end statement.   
<pre>
<code lua>
Example:
Example:
if game.Workspace == game.Lighting then
if Workspace == game.Lighting then
print("No way!")
print("No way!")
else
else
print("Whew. That was close.")
print("Whew. That was close.")
end
end
</pre>
</code>
Well, there's the 'if' statement's condition, which returns false. It then goes to the 'else' statement and executes to the end statement.
Well, there's the 'if' statement's condition, which returns false. It then goes to the 'else' statement and executes to the end statement.


Line 116: Line 116:
'Elseif' is not an 'if' function. So what is the difference between 'elseif' and 'else if'?  'Elseif' is counted as an 'else' with a requirement for it to be run, and doesn't need an end. On the other hand, 'else if' is comprised of two statements: an else, and an if.  Therefore, it needs a 'end' for the extra 'if' statement. 'Elseif' is A secure than 'else', because the lines of script after it '''only''' runs if the condition after the 'elseif' is met. Unless you want the folowing lines to be run '''only ''' if the 'if' statement is false, then use 'elseif' to make sure that the lines only run if the 'elseif' condition is met.
'Elseif' is not an 'if' function. So what is the difference between 'elseif' and 'else if'?  'Elseif' is counted as an 'else' with a requirement for it to be run, and doesn't need an end. On the other hand, 'else if' is comprised of two statements: an else, and an if.  Therefore, it needs a 'end' for the extra 'if' statement. 'Elseif' is A secure than 'else', because the lines of script after it '''only''' runs if the condition after the 'elseif' is met. Unless you want the folowing lines to be run '''only ''' if the 'if' statement is false, then use 'elseif' to make sure that the lines only run if the 'elseif' condition is met.


<pre>
<code lua>
--GOOD
--GOOD
score = 12
score = 12
Line 127: Line 127:
print("Doing OK!")
print("Doing OK!")
end
end
</pre>
</code>


<pre>
<code lua>
--BAD
--BAD


Line 139: Line 139:
end
end
end
end
</pre>
</code>


'Elseif' doesn't need an end, but 'else if' does, because Example 2A and Example 2B are the same.
'Elseif' doesn't need an end, but 'else if' does, because Example 2A and Example 2B are the same.
Line 146: Line 146:
This will execute the block of code once, then keep on repeating until the 'until' condition is neither nil nor false.
This will execute the block of code once, then keep on repeating until the 'until' condition is neither nil nor false.


<pre>
<code lua>
a = 0
a = 0
repeat
repeat
Line 152: Line 152:
until a == 1
until a == 1
print("a equals to 1!")
print("a equals to 1!")
</pre>
</code>


===The 'end' Statement===
===The 'end' Statement===
Line 158: Line 158:


Example for 'if':
Example for 'if':
<pre>
<code lua>
value = true
value = true


Line 164: Line 164:
print ("You are correct!")
print ("You are correct!")
end
end
</pre>
</code>


Example for 'for':  
Example for 'for':  
<pre>
<code lua>
children = game.Workspace:GetChildren()
children = Workspace:GetChildren()
for k, child in pairs(children) do
for k, child in pairs(children) do
if child:IsA("Part") and not child.Locked then
if child:IsA('Part') and not child.Locked then
child:Remove()
child:Destroy()
end
end
end
end
</pre>
</code>


Example for 'while':
Example for 'while':
<pre>
<code lua>
while workspace:FindFirstChild("Ball") do  
while Workspace:FindFirstChild("Ball") do  
workspace.Ball:Destroy()
Workspace.Ball:Destroy()
wait(1)
wait(1)
end
end
</pre>
</code>


Example for function:
Example for function:
<pre>
<code lua>
function anchor(part)
function anchor(part)
part.Anchored = true
part.Anchored = true
end
end


anchor(game.Workspace.Base)
anchor(Workspace.Base)
</pre>
</code>


===The 'local' Statement===
===The 'local' Statement===
Line 197: Line 197:


Example:
Example:
<pre>
<code lua>
bin = script.Parent
bin = script.Parent


Line 211: Line 211:


bin.Touched:connect(onTouched)
bin.Touched:connect(onTouched)
</pre>
</code>


For the above code, if the variable `h` was not set as local, and two people touched the brick, only one person would be taking damage. However, since the `h` variable is local, it re-defines a new local `h` variable each time the function is called, thus allowing the function to not bug up when running twice at the same time.
For the above code, if the variable `h` was not set as local, and two people touched the brick, only one person would be taking damage. However, since the `h` variable is local, it re-defines a new local `h` variable each time the function is called, thus allowing the function to not bug up when running twice at the same time.
Line 217: Line 217:
If you don't use the local keyword, any assignment is considered the opposite - global. Global things can be used anywhere in a script (not just in the chunk of code it is defined in). Consider this:
If you don't use the local keyword, any assignment is considered the opposite - global. Global things can be used anywhere in a script (not just in the chunk of code it is defined in). Consider this:


<pre>
<code lua>
a = "apple" --global `a` is "apple"
a = "apple" --global `a` is "apple"


Line 228: Line 228:


doSomething()
doSomething()
</pre>
</code>


===The 'while' Statement===
===The 'while' Statement===
Line 234: Line 234:


Example one:
Example one:
<pre>
<code lua>
while true do --this repeats forever since "true" is always neither nil nor false
while true do --this repeats forever since "true" is always neither nil nor false
wait(3)
wait(3)
print("Hello World!")
print("Hello World!")
end
end
</pre>
</code>


We can also instead of putting the wait after while true do, inside it!
We can also instead of putting the wait after while true do, inside it!
Line 245: Line 245:
For example:
For example:


<pre>
<code lua>
while wait(3) do
while wait(3) do
  print("I waited three seconds, and this message came up")
  print("I waited three seconds, and this message came up")
end
end
</pre>
</code>


Another example:
Another example:
<pre>
<code lua>
energy = 0
energy = 0
while energy < 10 do
while energy < 10 do
Line 260: Line 260:
energy = energy + 1
energy = energy + 1
end
end
</pre>
</code>


Example one shows a function that will never end. Example two shows how a condition is tried each time the loop ends.
Example one shows a function that will never end. Example two shows how a condition is tried each time the loop ends.
Line 269: Line 269:
Numeric for is generally considered easier than generic because of it's simplicity. The format for numeric for statements is:
Numeric for is generally considered easier than generic because of it's simplicity. The format for numeric for statements is:


<pre>
<code lua>
for a = b, c, d do
for a = b, c, d do
--code
--code
end
end
</pre>
</code>


Lua first defines a local variable `a` as `b` (`b` must be a number). It will then execute the code, and add `d` to `a`. It repeats the process until `a` is greater than or equal to `c`. You can leave out `d` and Lua assumes 1 as d.
Lua first defines a local variable `a` as `b` (`b` must be a number). It will then execute the code, and add `d` to `a`. It repeats the process until `a` is greater than or equal to `c`. You can leave out `d` and Lua assumes 1 as d.


Example one: (numeric for)
Example one: (numeric for)
<pre>
<code lua>
for i = 1, 10 do
for i = 1, 10 do
print(i)
print(i)
end
end
</pre>
</code>
This executes the block of code 10 times, incrementing i by 1 each time until it is 10. Notice how the delta amount (the amount that is added)  
This executes the block of code 10 times, incrementing i by 1 each time until it is 10. Notice how the delta amount (the amount that is added)  
is omitted and Lua assumes 1.
is omitted and Lua assumes 1.
Line 291: Line 291:


Example Two:
Example Two:
<pre>
{{Code and output
|code=
a = {"Hello", true, 1337}
a = {"Hello", true, 1337}
a.derp = "herp"
a.derp = "herp"
Line 297: Line 298:
print(key, value)
print(key, value)
end
end
</pre>
|output=
 
This runs the chunk of code for every value in the `a` table. As such, the output of this code is:
 
<pre>
1 Hello
1 Hello
2 true
2 true
3 1337
3 1337
derp herp
derp herp
</pre>
}}
 
This runs the chunk of code for every value in the `a` table.


Generic for-statements can be used to easily go through the children of an object:
Generic for-statements can be used to easily go through the children of an object:


Example Three:
Example Three:
<pre>
<code lua>
bricks = 0
bricks = 0
a = game.Workspace:GetChildren()
a = Workspace:GetChildren()
for k, v in pairs(a) do
for k, v in pairs(a) do
if v:IsA("Part") then
if v:IsA("Part") then
Line 320: Line 319:
end
end
print("Bricks: " .. bricks)
print("Bricks: " .. bricks)
</pre>
</code>


== See also ==
== See also ==


<br>[[Built-in functions]]
*[[Built-in functions]]
<br>[http://www.lua.org/pil/4.3.1.html Programming in Lua]
*[http://www.lua.org/pil Programming in Lua]


[[Category:Scripting Tutorials]]
[[Category:Scripting Tutorials]]

Revision as of 05:15, 21 January 2012

What You Need!

  • ROBLOX Studio
  • Explorer Tab - This tells you exactly where everything is.
  • Properties Tab - This tells you all the things editable in an object.
  • Output - A scripter's best friend. It tells you any mistakes (syntax, values, etc) found in a script, and where to find it.
  • Command Bar (Optional) - Not really needed, but is a great way to test out one-lined wonders.
  • Any script; new or old (Optional) - If you want an example script to look at, you can always pick one out of the toolbox.

Order of Operations; Script Style (VFC)

There is an order of which you should add your operations, just like in math. A mnemonic device for this order is "VFC", for "Variables, Functions, and Connections". A good script usually has itself in a neat and tidy order so that almost anyone can understand what the script does just by looking at it.

Variables

Usually in a script, there is a specific order in which you put your operations. First off, one of the most important things to put in the very beginning are variables. Variables are used to note objects that will be used a lot. If you like to be organized, you like to put things in models. Sometimes, that model chain can get pretty lengthy.

Example: example = Workspace.Example

Notice how the variable has a name, which is "example." The name can be anything except numbers alone. If you have a name of just numbers and you use it in a script, you will end up with a syntax error. When defining a variable, you need to tell exactly where it is. The Explorer tab helps with this as there is always a little tab telling you that that object is a child of something. When typing the parental of the object you want, spell the parental(s) correctly. You do not need the function ":FindFirstChild()" when making variables.

Functions

Secondly, in many scripts, you will come across a function. A function is something that can be used repeatedly. Some functions are also used to shorten script length, and some are just there because someone didn't want to delete it. When I create functions, I create the ones without a connection first, and then I create the ones with a connection line afterwards. If I do it like this, I can use the non-connections in the ones with connections. After all the things inside, you always close a function with an "end" statement.

Example: bin = script.Parent

function anchor(object) object.Anchored = true end

function onTouched(part) anchor(part) end

bin.Touched:connect(onTouched) There is the one variable, not really needed but I need to stress its importance. In the first function, as in every function, the term "function" is first. It is correct if the term turns purple. After the term "function," the function needs to be named (in the example, there are two -- named "anchor" and "onTouched".) Do not use numbers as a name. It is better to spell out numbers in names, except in some occasions. Now, after the name, you'll see the word "object" in parentheses. You can rename it anything you want, except numbers, and you can use it for anything you want. It's like a function variable, you can use it to do other things and use it repeatedly with different terms. You can also add more variables to this by using commas. So, this example could have been made: "function anchor(object, statement)". In this function, though, it is anchoring the object no matter what. Finally, the "end" statement.

In the second function, the function has a connection line. It's the same as the first function, the "function" statement, the function name, and the variable. The difference is, the previous function anchors the so-called "part." The variable is defined as "part," which is in this case, the object being touched. Finally, the "end" statement as always.

Connection Lines

If you look in the above example, you will notice a connection line. A connection line does what it says, connects the function to something happening in a place. The layout for a connection line is very simple. Connection lines usually tell you that the script is doing and when.

Example: bin = script.Parent

function anchor(object) object.Anchored = true end

function onTouched(part) anchor(part) end

bin.Touched:connect(onTouched) --this is called the "connection line" Presuming this script is inside of a brick, it can therefore be touched. In the variables, the brick is called "bin." In the connection line, there is a specific order in which the line should be. It should be like this:

<Object>.<Event>:connect(<Function>)

The object "bin" (a brick) has an event called "Touched" which is being connected to the function "onTouched".

To find events for objects, check the Object Browser.

Basic Lua Keywords

Throughout Lua, you will find terms like 'if', 'local', and 'for'. In this section, I will teach you Basic Lua terms. I recommend, if you haven't, to read the Order of Operations section of this guide before going on with this one.

The if Statement

The if control structure takes one value directly after "if", and then the keyword "then", followed by a block of code that finishes with "end" (or an else statement). The if statement always executes the block of code after "then" unless the value given to it is either nil or false.

[1]

Example One

brick = Workspace:findFirstChild("Brick") if brick then print("The brick is here!") end In this snippet of code, the brick variable is defined as whatever is given by FindFirstChild. The if statement will check if the `brick` variable is neither nil nor false. If the FindFirstChild function returned a brick, then the if statement block of code will be run.

A common mistake when writing if-blocks is using a single equals sign instead of two. One equals sign is an assignment operator, not an equality operator. Use two equals signs when checking for equality!

Example Two

number = 0 while number < 10 do wait(1) number = number +1 if number > 5 then print("Number Greater Than 5!") end end On the first line, "number" is 0. The next step is a 'while true do' loop. It waits one second then "number" will increase by one. Then there is the 'if' statement. It is now asking if "number" is greater than 5. If "number" is greater than 5, it will print, "Number Greater Than 5!" If it isn't greater than 5, then it will just skip it and repeat the loop. Once "number" turns to 11, the loop will end. This also goes with connection functions.

TIP: When using 'if' statements, use the proper Operations of comparison.

The 'else' Statement

Say you have an 'if' function, but it has false or nil inside. That's when the 'else' kicks in. It does the function of the else onward to the end statement. Example: if Workspace == game.Lighting then print("No way!") else print("Whew. That was close.") end Well, there's the 'if' statement's condition, which returns false. It then goes to the 'else' statement and executes to the end statement.

The 'elseif' Statement

'Elseif' is not an 'if' function. So what is the difference between 'elseif' and 'else if'? 'Elseif' is counted as an 'else' with a requirement for it to be run, and doesn't need an end. On the other hand, 'else if' is comprised of two statements: an else, and an if. Therefore, it needs a 'end' for the extra 'if' statement. 'Elseif' is A secure than 'else', because the lines of script after it only runs if the condition after the 'elseif' is met. Unless you want the folowing lines to be run only if the 'if' statement is false, then use 'elseif' to make sure that the lines only run if the 'elseif' condition is met.

--GOOD score = 12

if score < 5 then --if score is below 5 print("Losing!") elseif score > 10 then --if score is above 10 print("Winning!") else --logically, if score is between 5 and 10 (inclusively) print("Doing OK!") end

--BAD

if score < 5 then print("Losing!") else if score > 10 then print("Winning!") end end

'Elseif' doesn't need an end, but 'else if' does, because Example 2A and Example 2B are the same.

The 'repeat' Statement

This will execute the block of code once, then keep on repeating until the 'until' condition is neither nil nor false.

a = 0 repeat a = a + 0.1 until a == 1 print("a equals to 1!")

The 'end' Statement

This statement terminates an "if", "while", "for" or "function" statement's chunk of code.

Example for 'if': value = true

if value then print ("You are correct!") end

Example for 'for': children = Workspace:GetChildren() for k, child in pairs(children) do if child:IsA('Part') and not child.Locked then child:Destroy() end end

Example for 'while': while Workspace:FindFirstChild("Ball") do Workspace.Ball:Destroy() wait(1) end

Example for function: function anchor(part) part.Anchored = true end

anchor(Workspace.Base)

The 'local' Statement

The 'local' statement makes a variable usable in only the chunk of code it is defined in.

Example: bin = script.Parent

function onTouched(part) local h = part.Parent:FindFirstChild("Humanoid") if h then while h.Health > 10 do h.Health = h.Health - 10 wait(1) end end end

bin.Touched:connect(onTouched)

For the above code, if the variable `h` was not set as local, and two people touched the brick, only one person would be taking damage. However, since the `h` variable is local, it re-defines a new local `h` variable each time the function is called, thus allowing the function to not bug up when running twice at the same time.

If you don't use the local keyword, any assignment is considered the opposite - global. Global things can be used anywhere in a script (not just in the chunk of code it is defined in). Consider this:

a = "apple" --global `a` is "apple"

function doSomething() local a = "banana" print(a) --> "banana" a = nil --sets the local variable to nil print(a) --> "apple" (using the global variable) end

doSomething()

The 'while' Statement

The while statement is another kind of loop. The block of code will be executed as long as the condition between 'while' and 'do' is neither nil nor false. Note that in ROBLOX, you should always use wait() in your while statements to prevent ROBLOX from freezing and crashing!

Example one: while true do --this repeats forever since "true" is always neither nil nor false wait(3) print("Hello World!") end

We can also instead of putting the wait after while true do, inside it!

For example:

while wait(3) do

print("I waited three seconds, and this message came up")

end

Another example: energy = 0 while energy < 10 do wait(3) print("Charging up...") print(energy) energy = energy + 1 end

Example one shows a function that will never end. Example two shows how a condition is tried each time the loop ends.

The 'for' Statement

The 'for' statement is another type of loop. There are two kinds - generic and numeric. One works with tables and iterator functions, and the other with numbers.

Numeric for is generally considered easier than generic because of it's simplicity. The format for numeric for statements is:

for a = b, c, d do --code end

Lua first defines a local variable `a` as `b` (`b` must be a number). It will then execute the code, and add `d` to `a`. It repeats the process until `a` is greater than or equal to `c`. You can leave out `d` and Lua assumes 1 as d.

Example one: (numeric for) for i = 1, 10 do print(i) end This executes the block of code 10 times, incrementing i by 1 each time until it is 10. Notice how the delta amount (the amount that is added) is omitted and Lua assumes 1.

Generic for statements are a bit more difficult because they use iterator functions. Iterator functions give you the next value in some kind of list each time they are run. Lua runs the function until the iterator function does not give a value back. That's really complicated to know. In Lua, you can use the pairs() function right inside the for statement to generate an iterator function for that table.

This is a lot easier done than said. Consider this example.

Example Two:

a = {"Hello", true, 1337}
a.derp = "herp"
for key, value in pairs(a) do
	print(key, value)
end

1 Hello 2 true 3 1337

derp herp

This runs the chunk of code for every value in the `a` table.

Generic for-statements can be used to easily go through the children of an object:

Example Three: bricks = 0 a = Workspace:GetChildren() for k, v in pairs(a) do if v:IsA("Part") then bricks = bricks + 1 end end print("Bricks: " .. bricks)

See also