Roblox Wiki
Advertisement
Roblox Wiki
Tutorial page
This article is an intermediate tutorial.

Welcome to Intermediate scripting! If you have not already, please check out the Beginner guide to scripting. This scripting tutorial will teach you about how to script at an intermediate level. We'll move beyond the simply equal sign statement and use more complex coding conventions.

Just a Quick Review[]

Here are some concepts you should know beforehand:

Newbie's Guide[]

  • The Home Tab contains several tools to insert and manipulate shapes.
  • Three-dimensional shapes in Roblox are called parts, and you can modify its shape, size, colour, texture and name.
  • A script contains the code.
  • The Explorer window is the list of all the objects in the game, and it has a hierarchal structure.
  • To create a path to an instance, you start with the word game then work your way down the hierarchy.
  • In the Explorer window's hierarchy, a parent is one step above its child.
  • A complete statement must perform an action on an instance.

Beginners' Guide[]

  • The properties of an object determine its visible characteristics.
  • The output window is the primary tool for fixing coding errors.
  • A variable is a piece of text representing numbers, text, booleans or instances.
  • Variables can be declared, updated and accessed.
  • The .new() constructor creates a new value for certain properties.
  • Vector3 is a value type that determine the coordinates of an object in a three-dimensional space.
  • A function is a piece of code that can be used multiple times.

You should have Roblox Studio open for this, and you should also have a script open as well as your Explorer, Properties, and Output open.

If Statements[]

If statements are everywhere in life. If I wake up late, then I will be late for school. The same principle exists in coding. An if statement would run a piece of code if a condition is met. For example:

local Var = 1
if Var == 1 then
   print("condition met")
end

In Line 1, I am declaring a variable. I am using one equals sign because I am defining the variable.

In line 2, I am checking the variable to see if it is equal to 1. I use the double equals sign (==) operator to see if the condition is met.

What do you think would happen with this script?

local Var = 8
if Var + 8 == 40 then
   print("condition met")
end

Relational Operators[]

A relational operator compares two numbers.

  • == (equal to)
  • ~=(not equal to)
  • < (less than)
  • > (greater than)
  • <= (less than or equal to)
  • >= (greater than or equal to)

So for example, some statements would be:

(4 is less than 5.)

(1 is equal to 1.)

(49 is greater than 38.)

For reference, if you are confusing the greater than (>) and less than (<) symbols, I like to think of these symbols as an alligator mouth that "eats" the greater number. In the above equations, the alligator is eating the 5 and the 49 because they are the bigger numbers.

Arithmetic Operators[]

If you have any knowledge of mathematics, you should know that numbers can be changed with operators. These are:

  • + (add/plus)
  • - (subtract/minus)
  • * (multiply/times)
  • / (divide/divided by)
  • % (modulus/mod)
  • ^ (exponents/to the power of)

So...

(3 plus 6 is equal to 9.)

(18 times 59 is equal to 1062.)

(89 plus 21 is less than 102.)

You probably aren't familiar with two of these operators. Let me explain them:

Modulus[]

If you're familiar with division, you probably know that some numbers don't divide evenly. For example:

7 cannot be divided by 2 because there is 1 left over. Therefore...

Therefore, 7 mod 2 is 1. We call this the modulus operation, where we find the remainder of a number when it is divided. This operation is really only used in coding and you probably won't encounter this when dealing with regular math. Can you solve this one?

Well, 14 divided by 5 is 2, but 4 is left over. Therefore, 14 mod 5 is 4.

Exponents[]

Exponents are just repeated multiplication. In math, the little number on top tells you how many times you're multiplying the number by itself.

In this case, the little number tells you to multiply 5 by itself 3 times. Can you solve this one?

Well, the little number tells you to multiply 3 times itself four times. So...

Remember, there are no little numbers in coding. You need to use the caret symbol (^) to express exponents.

3^4 = 81

Performing an Operation on a Variable[]

It isn't very useful to only use operators on constant numbers. You can use these operators on variables, as long as the variable is a float or int value.

value = value + 1 --Adds 1 to the value.
value = value - 1 --Subtracts 1 from the value.
value = value / 2 --Divides the value by 2.
value = value * 3 --Multiplies the value by 3.
value = value % 3 --Divides the value by 3, then returns the remainder.
value = value ^ 5 --Multiplies the value by itself 5 times.

For added simplicity, these operations can be shortened, as these examples show:

value += 1 --adds 1 onto value
value -= 1 --(takes 1 off of value)
value *= 2 --(multiplies value by 2)

Here is an example of an arithmetic operator that tests whether or not the player has enough money:

if plr.Money.Value >= 120 then
    plr.Money.Value -= 120
end

Here, it checks if the player owns $120 or more. If so, it would subtract it.

Logical Operators[]

A logical operator combines two operators together into one. These are:

  • and (checks if BOTH conditions are true)
  • or (checks if EITHER condition is true)
  • not (checks if the current state is the OPPOSITE of the condition)
if value < 30 and value > 15 then
    --Code
end

if value == "cheese" or value == "pie" then
    --Code
end

if not value == 12 then
    --Code
end

The first if statement checks if the value is less than 30, but greater than 15. In other words, it checks if the value is between 15 and 30. The second if statement checks if the value is "cheese" or "pie", and the third checks if the value is not 12.

Truthy/Falsy Values[]

But what does this mean?

if value then
    print("Oof")
end

If there are no operators, the if statement checks if the value is truthy or falsy.

To be clear, a falsy value (also known as a falsey value), is a value that is either false or nil.

All other values are considered truthy values.

Most of the time, this is used to find if an instance exists. So, if I were to do this,

local Head = script.Parent:FindFirstChild("Head")

if Head then
    print("My parent has a head.")
end

I will explain later on what FindFirstChild() does later on, but basically, it finds the part named Head.

This script will check if its parent has a child named "Head". If it does, it prints.

Else, Elseif, and Nesting If Statements[]

You can also put one if statement inside another. This is called nesting an if statement.

local Var1 = 1
local Var2 = false
if Var1 == 1 then
    if Var2 == false
        print("Oof")
    end
end

The script will see that both conditions are met, so it prints. Remember, each, if statement needs its own end tag.

Placing else in the if statement will cause the script to run alternate code should the first condition not be met.

local Var1 = 1
if Var1 == 2 then
     print("condition met")
else
     print("condition not met")
end

An elseif is basically just combining "else" with an if statement. If the first condition is not met, it will check if a second condition is met.

local Var1 = 1
local Var2 = false
if Var1 == 2 then
     print("condition 1 met")
elseif Var2 == false then
     print("condition 2 met")
end

So, the system defines both variables, then has to decide whether Var1 is equal to 2. It is not, so it checks the other condition. It is met, so it prints out "condition 2 met." You can make if statements as crazy as you want, with as many elseifs and nested if statements as you want.

Service[]

Now, go to your Explorer window and close all the ˅ icons you see. You should see this:

These are services, which are of the highest level in the Explorer window. They all serve their individual functions. Here are the

  • Workspace: A service that holds all the parts and physical objects in the game.
  • Players: A service that manages all the players that enter the game.
  • Lighting: Manages the lighting effects, time of day, and the sun, moon and sky.
  • ReplicatedStorage: Service containing objects replicated to all clients
  • ServerScriptService: Service containing server scripts; scripts to be used for the whole game, i.e.: for leaderboards.
  • ServerStorage: Storage for objects to be used later.
  • StarterGui: Service that stores ScreenGuis.
  • StarterPack: Service that stores player tools.
  • SoundService: Storage for audio assets.
  • Chat: Manages chat.
  • LocalizationService: Manages auto-translation.

This is a lot to unpack, so focus on Workspace, as it is the most frequently used service, and the only one used in this tutorial. In the Advanced tutorial, we will start using StarterGui and ReplicatedStorage.

There are also two services you can manually add to the Explorer window: ReplicatedScriptService and Teams. To add them, open the View Tab > Command bar. Then, enter both of these commands in the bar:

game:GetService("ReplicatedScriptService")
game:GetService("Teams")

These services will then appear in your Explorer.

Of course, there are many other services hidden away from the Explorer window. To access them inside a script, you need to use the GetService() function to get the service. For example:

local UserInputService = game:GetService("UserInputService")

Now, within the script, the service UserInputService will be contained inside the "UserInputService" variable.

Parameters[]

Think of a microwave and how it works. It can heat up your food, but you need to input some information: how long you want it to run, and how hot it needs to be. After you enter that information, the microwave then uses that information to cook your food.

This is like a function. You can create a function that needs you to input a few values for it to run. These values, which can only be used inside the function, are called parameters or arguments.

Let's try this; start by declaring a function.

function write()
    
end

Now, name your parameter, placing the name in the brackets ().

function write(MyNumber)
    
end

Now, when you call the function, you have to insert the value for MyNumber in the brackets.

function write(MyNumber)
    
end
write(3)

Here, I am defining the parameter MyNumber as 3. Now, I can use MyNumber as a variable in the function. With the below code, what do you think will appear in the output?

function write(MyNumber)
    MyNumber += 2
    print(MyNumber)
end
write(3)

This function inputs the number 3, adds 2 to it, then prints the final result in the output. Therefore, "5" will appear in the output window.

Tuples[]

We can also do this:

function write(stuff, morestuff)
    print(stuff)
    print(morestuff)
end
write("Hello","world!")

The above script expects two parameters: stuff and morestuff. When calling the function, we define stuff as Hello and morestuff as world!.

You can have as many parameters as you want as long as you separate them with commas. When we use more than one argument, we call it a tuple.

Returning[]

We know how to input values into a function, but how do you output it? It isn't very useful to print the result in the output window because you can't use that value within the script.

Let's use the example from the parameters section. We have already created a function that takes in an input.

function write(MyNumber)
    MyNumber += 2
    print(MyNumber)
end
write(3)

This code posts the final result, 5, in the output window, but what if I want to use that value again? You have to use the return function.

function write(MyNumber)
    MyNumber += 2
    return MyNumber
end
local answer = write(3)

When you return a value, you place the final value inside a variable. The above function returns the number 5 and places it inside the answer variable. This way, you can do this:

function write(MyNumber)
    MyNumber += 2
    return MyNumber
end

local answer = write(3)

function writeagain(Number2)
    Number2 += 6
    return Number2
end
local finalanswer = writeagain(answer)

Here, I'm creating a second function, using the previous answer. Can you guess what finalanswer would be?

Events[]

How does a mousetrap work? When it detects a mouse on it, it snaps shut and traps the mouse. This is basically how an event works: it detects something and reacts to it by firing a function. Let's try this. We're going to create a script that reacts when a part is touched. Create the following:

Make sure that the part is floating a little bit over the baseplate and anchor it. Now, enter the script.

Declare a function that fires the code you want when the part is touched.

function onTouch()
   print("i was touched D=")
end

Here, I am declaring a function called onTouch that prints the message "i was touched D=" in the output. One part is missing: you've declared the function but you can't activate it.

All baseparts have an event called Touched that fires whenever it is touched. You reference them like this:

function onTouch()
   print("i was touched D=")
end
script.Parent.Touched:Connect()

There are a few things to cover. Firstly, script.Parent refers to the part being touched. You use the Touched event. Lastly, you use Connect() to connect the event to the function onTouch(). In other words, whenever the event is fired, the function is fired as well.

Events also have built-in parameters. In the Touched event, its parameter is the person or thing that touched it.

function onTouch(whotouched)
   whotouched:Destroy()
end

script.Parent.Touched:connect(onTouch)

In this case, you call the thing who touched the object "whotouched." So, when you trigger the event, it fires the function, and the function destroys the thing that triggered the event.

There are a plethora of other events, but for intermediate scripters, Touched will be the most important one.

Another way to fire an event is to do this:

script.Parent.Touched:Connect(function(whoTouched)
    whoTouched:Destroy()
end)

This is a way to use less lines.

Instance[]

We already know that an instance is any object or property in the game. What if you want to create a script that creates a part out of nowhere? We use the .new() constructor to create a new instance.

local Brick = Instance.new("Part",game.Workspace)

Here, I am creating a new instance. The first parameter, "Part," is the class name of the instance, or what type of object it is. So, I am creating a part. It also has a second parameter, for its parent.

However, this is a common bad practice. It's never a good idea to use the Parent parameter. This only makes the function slower.

Instead, define the parent in the next line.

local Brick = Instance.new("Part")
Brick.Parent = game.Workspace

What if we want to set properties? Simple. After the above code, type this:

Brick.Transparency = 1
Brick.Name = "Block"

The system already knows what Brick means. Just set the properties.

Built-In Functions[]

These are the functions that are set in the game, and no custom function can be declared with the name.

Destroy()[]

This function effectively sets the object's parent to nil, removing it from the game. For example:

script.Parent:Destroy()

Clone()[]

Makes a duplicate of the part, with all of the same properties, except the parent. You still need to define it in the next line.

local Clone = script.Parent:Clone()
Clone.Parent = game.Workspace

ClearAllChildren()[]

Destroys all of the object's children. As an example, if you were to use this on workspace, it would delete everything in the workspace.

script.Parent:ClearAllChildren()

FindFirstChild()[]

If you are unsure of whether or not a variable or Instance exists, FindFirstChild() will access the object if it exists; if not, then the script will still run. Without a FindFirstChild function, you are essentially trying to access an instance that doesn't exist, so the code will break.

local fire = script.Parent:FindFirstChild("Fire")

If you want to run code if something exists, you simply use an if statement.

local fire = script.Parent:FindFirstChild("Fire")
if fire then
    print("FIIIREEE!")
end

WaitForChild()[]

Similar to FindFirstChild, but instead of returning a nil value if the object doesn't exist, it would yield, or wait. In other words, it will stop the script until it finds the object.

game.Workspace:WaitForChild("Part")
print(1)

Here, the script will wait for an instance named "Part," and will never continue on until it exists.

Wait()[]

Delays a code a set number of seconds. Set the time in seconds as the parameter in the brackets. If you don't put a number in the brackets, it will wait one second by default.

wait(0.5) --Delays half a second.
wait() --Delays 1 second.
wait(2) --Delays 2 seconds.

Tables[]

Tables, also known as arrays, are a type of variable in Lua that can be used to store multiple pieces of data in the same variable, for example:

local MyTable = {"a","b","c"}

MyTable is a variable that stores three string values: "a," "b," and "c."

All the values in a table have two values: an i value and a v value. i represents the index position, meaning its position in the table. Therefore, the first value has an i value of 1, the second value has an i value of 2, and so on. v represents the value itself, so in the above example the v values are a, b, and c

So, if you want to find the v value given the i value, you would have to do this.

a[2]

What this basically does is tells our script to access the second value in the table a. Now, say we wanted to print the last 2 values out of the following table:

a = {"three thousand","nine hundred","and one"}

What we would do is this:

 print(a[2])
 print(a[3])

We can also assign values to individual spaces within a table:

a[2] = "lol"
print(a[2])

This would print the text lol in our output, because the value of the second space in the table "a" was changed to "lol".

Loops[]

A loop is basically a chunk of code that executes repeatedly. Note that regardless of what type of loop you use, you MUST use a wait function (delay). This is because the system can run the code so many times so infinitely fast that without a delay, the server will crash and stop responding.

While Loops[]

The most simple loop is a "while" loop, that basically acts like this:

 a = true
 while a == true do
     wait(0.1)
     print("I can swing my sword")
 end

Basically what this does is the script continually checks if a is still true every .1 seconds, and if a is still true then the code within the loop will execute again.

If you wanted a while loop to keep executing code unconditionally, you would do this:

while true do
    --Code
end

Remember to keep a wait statement!

For Loops[]

A second, more complicated loop is the "for" loop, which can repeat a set number of times, for example:

 for i = 1,6 do
     wait(0.1)
     print("Hello mom!")
 end

Basically what this does is it makes the script count from 1 to 6, executing the code each time. So, "Hello mom!" would be printed 6 times.

If you want to get fancy...

Adding the third part causes our for loop to count in 2's meaning our script will count from 2 to 6 in 2's, and run every time you can add 2 to 2 before it becomes 6.

 for i = 2,6,2 do
     wait(0.1)
     print("Hello dad!")
 end

We can also print i:

 for i = 1,6 do
    wait(0.1)
    print(i)
 end

What this basically makes our script do is count from 1 to 6 and every single time it counts up 1, it prints whatever value it is at.

In Pairs Loops[]

This loop will require an understanding of tables, which you should have learned about above.

An in pairs loop is a loop that involves the values in a table.

local Parts = game.Workspace.Folder:GetChildren()
for index,Part in ipairs(Parts) do
     print(index)
     Part:Destroy()
     wait(0.5)
end

What GetChildren() does is that it returns an array containing all instance values inside each folder. Then, I renamed i to index and v to Part. Then, I told the script what table I wanted to use after "in pairs." Then, between half-second intervals, the script would count the number of parts as it destroys each part one by one.

What Does 'local' Mean?[]

In the Beginners' Tutorial, I mentioned that variables should have 'local' in front of it. Now that you've learned some important skills, I can explain what it means.

Understanding Blocks

To understand this, you need to understand blocks. You will notice that I asked that you indented code in if statements, functions and loops. The entire code is a block of code within itself, and any code inside loops, functions, and if statements are another block. You can see with the image on the right that there are four levels of blocks in that script.

So what does 'local' mean? Well, it means that the variable can only be accessed within that block. This keyword is similar to JavaScript let. So if I were to use the following code:

local db = false
if db == false then
    local var = 1
end
print(var)

The script would error, because the print statement is trying to access a variable that can only be accessed within the if statement.

local db = false
local var
if db == false then
    var = 1
end
print(var)

You can see that on the second line, I have not given a value to var, therefore it is automatically set to nil. Then, the if statement will cause var to equal 1. It is no longer 'local' because the if statement is simply updating an already-existing variable.

Intermediate Scripting: Examples[]

Multi-Purpose Killing/Healing Brick (Difficulty: Medium-Hard)[]

Great! Now that we have our concepts down, let's get cracking. Say, we wanted a brick that removed Shedletsky's head whenever he stepped on it, but it would heal other players when they stepped on it. So, create a script and put it inside a brick using the explorer - Next, let's create our function that will be called by the Touched event and our value that will be assigned by the Touched event (to check if it's actually Shedletsky, of course!):

 function touch(shedletskycheck)

Great! We have the function touch with the argument shedletskycheck. Now we have to state what our function does. We want our function to first check for Shedletsky:

 function touch(shedletskycheck) 
 '''if shedletskycheck.Parent.Name == "Shedletsky" then'''

The script now checks for if whatever touched the brick's parent's name was Shedletsky. Now we must create a path leading from the touching brick to Shedletsky's head:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
--We navigated from shedletskycheck to its Parent, which is the Shedletsky model itself, then we found the Head within the Shedletsky model.

Now, let's say that something that WASN'T Shedletsky touched the brick. According to our script description, we must check if whatever that touched the brick that wasn't Shedletsky was even a player, then we must heal it. As such, we must find if the touching part's parent had a Humanoid in it. To do this, we must use a ;findFirstChild() method (If you don't know what this is, see Beginner guide to scripting.)

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then

Using the elseif statement, if the conditions for the previous "if" (Which is whoever touched the brick being Shedletsky") are not met, then the elseif statement checks the following condition (in this case, if the brick's parent actually even had a Humanoid in it, indicating whether or not whatever touched the brick was even a player), and then we ran a :findFirstChild() method on the touching part's parent, and if it found a Humanoid in the touching part's parent, it returns ~= nil, however if it did not find one, it returns nil.

Now, we need to heal them:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstchild("Humanoid") ~= nil then
 shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth

This basically sets the value of their health to their maxhealth, effectively healing them to full capacity. Hooray! We almost have our script. Now all we have to do is add one "end" for every "function" and "if" we have, excluding "elseif"s.

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth
 end
 end

We have one function and one if, excluding the "if" in "elseif", so we added two ends.

Lastly, we need to add the connection:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 shedletskycheck.Parent.Humanoid.Health = shedletsky.Parent.Humanoid.MaxHealth
 end
 end
 script.Parent.Touched:connect(touch)

Hooray! Now if we run our script in Play Solo, if you rename a character Shedletsky, when it touches the brick, its head should be removed! However, if you damage yourself and you touch the brick, you should be healed back up to full health!

Extension: Extended Healing Effect[]

Now let's say that we didn't want our brick to heal other players up instantly, but instead it would heal them in 20's every 5 seconds 5 times. You guessed it: We're using "for" loops.

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 end
 end
 script.Parent.Touched:connect(touch)

So we replaced the initial healing code with a "for" loop that counts from 1 to 5 (from 1 to 5 times), next we must add the healing code to make the Humanoid gain 20 extra health (I used a variable to define the humanoid in this case to shorten the code, however it's not necessary) and add the wait method that makes the script wait 5 seconds before adding more health:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 wait(5)
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 script.Parent.Touched:connect(touch)

So we added a wait statement that makes the script wait 5 seconds, then it - of course - found the Humanoid, and set its value to its original value plus 20. (A Variable's value is non-constant, it is whatever it was when its value was set. The variable does not continually update itself. Hence:

 a = 1
 b = a
 wait(1)
 a = 2
 print(b)

Would actually display 1, since at the time b was set to a, a was 1, however later on a was changed to 2, but since variables are non-constant, b remained 1.)

Now, lastly, we must end the loop with an "end":

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 wait(5)
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end
 script.Parent.Touched:connect(touch)

If you did this correctly, when you step on the scripted block in Play Solo, if you're damaged, you should slowly be gaining Health (unless your name is Shedletsky.)

Extension: Disappearance Effect[]

Now, let's say we wanted our script to continually increase the transparency of Shedletsky's head every .1 second, and when his head's transparency reaches 1, ONLY THEN the script will remove Shedletsky's head. We're going to be using some more "for" loops. (I used a variable to define shedletsky's head's transparency, but you don't have to)

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end 
 script.Parent.Touched:connect(touch)

So we replaced the basic transparency setting code with a "for" loop that counted from 1 to 10 and defined shedletsky's head's transparency as the variable trans. Now, we must add the part where his transparency is increased:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 trans = trans + 0.1
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end 
 script.Parent.Touched:connect(touch)

So now this will increase the head's transparency by .1 10 times (a transparency value of 1 causes a brick to be fully invisible). Now we have to add the statement that makes the script wait .1 seconds between transparency increases:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end 
 script.Parent.Touched:connect(touch)

Lastly, we add the end statement:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end
 script.Parent.Touched:connect(touch)

And the part that removes Shedletsky's head:

 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end
 script.Parent.Touched:connect(touch)

So now, when you run the script in Play Solo, if you name yourself Shedletsky, when you step on the brick your head should gradually disappear until you die.

Player Recording[]

So let's say at this point you wanted to record all the non-Shedletsky players that will step on this brick, for this we must use a table:

 t = {one}
 function touch(shedletskycheck)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end
 script.Parent.Touched:connect(touch)

We've created a table with the content "one". This will help later on. Next, get the max number of our table by using the table.maxn() method, which returns the highest space in the table:

 t = {one}
 function touch(shedletskycheck)
 maxn = table.maxn(t)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 end
 end
 script.Parent.Touched:connect(touch)

Now, we must have our table insert the names of the recorded players using the table.insert() method - table.insert(table,location,value):

 t = {one}
 function touch(shedletskycheck)
 maxn = table.maxn(t)
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 table.insert(t,(maxn - 1),shedletskycheck.Parent.Name)
 end
 end
 script.Parent.Touched:connect(touch)

What this does is it gets the highest place in the table, subtracts it by one, and inserts the name value there. We do this to make sure that the table will add in a new name in a new space. Now, let's make it print the entire table when it's touched using two methods: the tostring method and the table.concat method. The table.concat method basically takes all the values in a table and squishes them together. The tostring method converts any value (such as a table value) to a string value.

 t = {one}
 function touch(shedletskycheck)
 maxn = table.maxn(t)
 print(tostring(table.concat(t,' ')))
 if shedletskycheck.Parent.Name == "Shedletsky" then
 trans = shedletskycheck.Parent.Head.Transparency
 for i = 1,10 do
 wait(0.1)
 trans = trans + 0.1
 end
 shedletskycheck.Parent.Head:remove()
 elseif shedletskycheck.Parent:findFirstChild("Humanoid") ~= nil then
 for i = 1,5 do
 b = shedletskycheck.Parent:findFirstChild("Humanoid")
 b.Health = b.Health + 20
 end
 table.insert(t,(maxn - 1),shedletskycheck.Parent.Name)
 end
 end
 script.Parent.Touched:connect(touch)

The VIP Door (Difficulty: Medium)[]

Now let's say you wanted a brick that only allows a certain person to pass through it but kills all others. Create a brick, firstly. Put a script in the brick, next, open its source. Firstly, we must create a function to be called by the Touched event and the value that will be defined by the Touched event:

 function onTouch(vip)

So we have a function onTouch and an argument "vip". Next, we create an "if" statement to check if whatever touched the brick was a player named "Bob":

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then

Our script now checks if the name of the parent of whatever touched the brick was Bob. Next, since we want our script to allow Bob to pass through, we set the value of the brick's cancollide to "false" for 1 second. The CanCollide property is the property that causes a brick to be solid.

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.CanCollide = true

Our script now, when touched by Bob, sets the brick's CanCollide to false, allowing Bob to pass through, and after 1 second - wait(1), it sets the brick's CanCollide to true, not letting others pass through. Now, we want Bob to know when the door is open, so we'll make the brick semitransparent while the brick's CanCollide is false:

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.Transparency = 0.5
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.Transparency = 0
 script.Parent.CanCollide = true

Our script now, when touched by Bob, not only changes the value of the brick's CanCollide, but also makes it semitransparent so Bob knows when the door is open. After 1 second - wait(1), at the same time the CanCollide is set to true, the transparency is set to 0 so that Bob knows when the door is closed. Next, we add the part that checks if (hypothetically speaking) whatever that touched the block that WASN'T Bob was even a player.

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.Transparency = 0.5
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.Transparency = 0
 script.Parent.CanCollide = true
 elseif vip.Parent:findFirstChild("Humanoid") ~= nil then

So if the conditions for the first "if" statement (the toucher being Bob) aren't met, then it performs an additional check that indicates whether the toucher was even a player. Now, the fun part: Killing the player.

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.Transparency = 0.5
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.Transparency = 0
 script.Parent.CanCollide = true
 elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
 vip.Parent.Humanoid.Health = 0

So our statement will now set the found Humanoid's health to zero. Lastly, let's close our "function" and or "if" (excluding our "elseif")

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.Transparency = 0.5
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.Transparency = 0
 script.Parent.CanCollide = true
 elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
 vip.Parent.Humanoid.Health = 0
 end
 end

And lastly, let's create the connection statement (which makes everything happen:)

 function onTouch(vip)
 if vip.Parent.Name == "Bob" then
 script.Parent.Transparency = 0.5
 script.Parent.CanCollide = false
 wait(1)
 script.Parent.Transparency = 0
 script.Parent.CanCollide = true
 elseif vip.Parent:findFirstChild("Humanoid") ~= nil then
 vip.Parent.Humanoid.Health = 0
 end
 end
 script.Parent.Touched:connect(onTouch)

Congratulations! If your script worked, anyone named "Bob" should be able to pass through the door, but anyone that isn't Bob will be killed by the door! You can change "Bob" to the name of your liking once you're ready to implement this into your place!

That's it for the intermediate guide! Go to the advanced scripting guide to continue.

Advertisement