In-Depth Scripting Guide: Difference between revisions
>Jaccob |
>JulienDethurens No edit summary |
||
Line 17: | Line 17: | ||
Example: | Example: | ||
< | <code lua> | ||
example = | example = Workspace.Example | ||
</ | </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: | ||
< | <code lua> | ||
bin = script.Parent | bin = script.Parent | ||
Line 39: | Line 39: | ||
bin.Touched:connect(onTouched) | bin.Touched:connect(onTouched) | ||
</ | </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: | ||
< | <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" | ||
</ | </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><Object>.<Event>:connect(<Function>)</pre> | <pre><Object>.<Event>:connect(<Function>)</pre> | ||
Line 76: | Line 76: | ||
====Example One==== | ====Example One==== | ||
< | <code lua> | ||
brick = | brick = Workspace:findFirstChild("Brick") | ||
if brick then | if brick then | ||
print("The brick is here!") | print("The brick is here!") | ||
end | end | ||
</ | </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==== | ||
< | <code lua> | ||
number = 0 | number = 0 | ||
while number < 10 do | while number < 10 do | ||
Line 96: | Line 96: | ||
end | end | ||
end | end | ||
</ | </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. | ||
< | <code lua> | ||
Example: | Example: | ||
if | 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 | ||
</ | </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. | ||
< | <code lua> | ||
--GOOD | --GOOD | ||
score = 12 | score = 12 | ||
Line 127: | Line 127: | ||
print("Doing OK!") | print("Doing OK!") | ||
end | end | ||
</ | </code> | ||
< | <code lua> | ||
--BAD | --BAD | ||
Line 139: | Line 139: | ||
end | end | ||
end | end | ||
</ | </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. | ||
< | <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!") | ||
</ | </code> | ||
===The 'end' Statement=== | ===The 'end' Statement=== | ||
Line 158: | Line 158: | ||
Example for 'if': | Example for 'if': | ||
< | <code lua> | ||
value = true | value = true | ||
Line 164: | Line 164: | ||
print ("You are correct!") | print ("You are correct!") | ||
end | end | ||
</ | </code> | ||
Example for 'for': | Example for 'for': | ||
< | <code lua> | ||
children = | children = Workspace:GetChildren() | ||
for k, child in pairs(children) do | for k, child in pairs(children) do | ||
if child:IsA( | if child:IsA('Part') and not child.Locked then | ||
child: | child:Destroy() | ||
end | end | ||
end | end | ||
</ | </code> | ||
Example for 'while': | Example for 'while': | ||
< | <code lua> | ||
while | while Workspace:FindFirstChild("Ball") do | ||
Workspace.Ball:Destroy() | |||
wait(1) | wait(1) | ||
end | end | ||
</ | </code> | ||
Example for function: | Example for function: | ||
< | <code lua> | ||
function anchor(part) | function anchor(part) | ||
part.Anchored = true | part.Anchored = true | ||
end | end | ||
anchor( | anchor(Workspace.Base) | ||
</ | </code> | ||
===The 'local' Statement=== | ===The 'local' Statement=== | ||
Line 197: | Line 197: | ||
Example: | Example: | ||
< | <code lua> | ||
bin = script.Parent | bin = script.Parent | ||
Line 211: | Line 211: | ||
bin.Touched:connect(onTouched) | bin.Touched:connect(onTouched) | ||
</ | </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: | ||
< | <code lua> | ||
a = "apple" --global `a` is "apple" | a = "apple" --global `a` is "apple" | ||
Line 228: | Line 228: | ||
doSomething() | doSomething() | ||
</ | </code> | ||
===The 'while' Statement=== | ===The 'while' Statement=== | ||
Line 234: | Line 234: | ||
Example one: | Example one: | ||
< | <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 | ||
</ | </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: | ||
< | <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 | ||
</ | </code> | ||
Another example: | Another example: | ||
< | <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 | ||
</ | </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: | ||
< | <code lua> | ||
for a = b, c, d do | for a = b, c, d do | ||
--code | --code | ||
end | end | ||
</ | </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) | ||
< | <code lua> | ||
for i = 1, 10 do | for i = 1, 10 do | ||
print(i) | print(i) | ||
end | end | ||
</ | </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: | ||
{{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 | ||
|output= | |||
1 Hello | 1 Hello | ||
2 true | 2 true | ||
3 1337 | 3 1337 | ||
derp herp | 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: | Generic for-statements can be used to easily go through the children of an object: | ||
Example Three: | Example Three: | ||
< | <code lua> | ||
bricks = 0 | bricks = 0 | ||
a = | 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) | ||
</ | </code> | ||
== See also == | == See also == | ||
*[[Built-in functions]] | |||
*[http://www.lua.org/pil Programming in Lua] | |||
[[Category:Scripting Tutorials]] | [[Category:Scripting Tutorials]] |
Revision as of 09: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.
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:
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)