roblox
Tutorial page
This article is an advanced tutorial.
Scripting
This page is a tutorial about Scripting.

Welcome! If you are reading this tutorial then you should have read the Newbie's, Beginners, Intermediate and Advanced Scripting tutorials. By now you should have all the skills to make a fully functional game. This tutorial will cover some random, non-fundamental concepts that you can use at any time.

Review

Here are the fundamental concepts mentioned in the four previous tutorials.

Newbie's Guide

Beginner's Guide

Intermediate Guide

Advanced Guide

Tick()

Tick() is a function that finds the Unix time. If you do not know what this means, it is number of seconds that have elapsed since the Unix epoch, which is January 1, 1970.

Let's say I wanted to find the amount of time that has passed since a GUI was clicked. Insert a ScreenGui, a TextButton into the ScreenGui, and a local script into the TextButton.

local startTime = tick()
script.Parent.Activated:Connect(function()
     local serverTime = tick() - startTime
     print(serverTime)
end)

Now it would take the current Unix time, then subtract the startTime from it.

Linear Interpolation

This is a handy alternative to tweening, allowing you to smoothly animate a part from one point to another. To do this, you can simply use the Lerp() function on the part's CFrame.

local GoalPart = game.Workspace.Part2
script.Parent.CFrame:Lerp(GoalPart.CFrame,0.5)

In the Lerp(x,y) function, x is the CFrame you want the part to end at, and parameter y is the decimal or fraction of the path you want the part to travel. So for example, when y = 1, the part would move all the way to the end CFrame. When y = 0, the part would not move at all. So in this case, the part would move halfway to Part2.

UDim2

UDim2 is the Gui equivalent of Vector3. Instead of handling a 3-dimensional space, it uses a 2-D space. Instead of taking in three values, it takes in four: X Scale, X Offset, Y Scale, and Y Offset.

Scale

Scale is the portion of the whole screen. So, when the X Scale on the GUI's size is set to 1, the GUI takes up the whole screen horizontally. When the X Scale is set to 0, the GUI cannot be seen.

Offset

Offset is the additional number of pixels. So, when the size is set to (0,300,0,300), the GUI will be 300 X 300 pixels. Note that you should avoid using Offset if possible because the GUI will become distorted depending on the screen.

It is recommended that when working with ScreenGuis, ALWAYS use Scale instead of Offset. This is because different devices have different screen sizes, so the UIs would look different on different screens.

Camera Manipulation

Changing the view of the camera is useful for a number of things. For example, you may want the camera to look at a certain tool when the player is in a shop in a simulator game. So, open StarterPlayer > StarterPlayerScripts and insert a local script.

local Camera = game.Workspace.CurrentCamera
local FocusPart = game.Workspace.FocusPart
local CameraCFrame = game.Workspace.CameraPart
wait(0.01)
Camera.CameraType = Enum.CameraType.Fixed
Camera.CFrame = CFrame.new(Vector3.new(CameraCFrame.Position))
Camera.Focus = FocusPart

In the third-to-last line, the CameraType was set to fixed, so it would stay at one point. Then, the location would be the position of CameraPart. Finally, setting the focus would make the camera stare at CameraPart.

UserInputService

UserInputService is a service primarily used to fire commands whenever a certain key was pressed. In this tutorial, you will learn to make an inventory GUI to appear whenever the E key is pressed.

Insert a ScreenGui and local script into StarterGui. Design the GUI to whatever fits you best.

InputBegan

InputBegan is an event that fires whenever a player tries to make an input into the game. This refers to not only typing a key, but also left or right clicking. So, in the local script enter the following code:

local UserInputService = game:GetService("UserInputService") 
UserInputService.InputBegan:Connect(function(input,gameProcessedEvent)
end

Now, you can see that there are two parameters for the InputBegan event: input and gameProcessedEvent. Input refers to the way that the player inputted data.

gameProcessedEvent

gameProcessedEvent is a boolean that is true if there would be no other reason for the user's input. For example, you likely wouldn't want this code to fire if the user typed E into the chat. You wouldn't want the code to fire if someone clicked on a GUI. In both of these occasions, gameProcessedEvent would be set to true. So, place an if statement that would only fire if gameProcessedEvent was false.

local UserInputService = game:GetService("UserInputService") 
UserInputService.InputBegan:Connect(function(input,gameProcessedEvent)
    if gameProcessedEvent == false then
    
    end
end)

Now, all that's left to do is check whether the input was a press of an E key. Then, use it to make the GUI enabled.

local UserInputService = game:GetService("UserInputService") 
UserInputService.InputBegan:Connect(function(input,gameProcessedEvent)
    if gameProcessedEvent == false then
          if input.Keycode == Enum.KeyCode.E then
               game.StarterGui.ScreenGui.Enabled = true
          end
    end
end)

KeyCode refers to the key that was pressed. Make sure to use Enum; string values will not work here.

InputEnded

InputEnded is a similar event, only it fires when the input ends. So, it fires when a user releases his mouse button or key.

local UserInputService = game:GetService("UserInputService") 
UserInputService.InputEnded:Connect(function(input,gameProcessedEvent)
    if gameProcessedEvent == false then
          if input.Keycode == Enum.KeyCode.E then
               game.StarterGui.ScreenGui.Enabled = true
          end
    end
end)

The "Enabled" Properties

The enabled properties are boolean properties that are set to true if the user's device has a certain feature. Here they are:

The "Touch" Events

These events fire whenever the user makes a certain motion using their finger on a mobile device.

Player Tools

You may also want to learn about player tools. These are tools that you can see in the inventory hotbar on the bottom of the screen.

To do this, first design your tool with as many components as you wish.

Next, find the main part you want the player to hold the tool by and rename it to "Handle". Note that you MUST use the exact name; Roblox won't accept any variation.

Then, weld all the parts together using weld constraints. You can do this by highlighting the parts in the Explorer, then going to Model > Constraints > Weld.

Insert a Tool into the Workspace and place all the parts inside it. You will notice, however, that the part may not be placed in your hand the way you want it to. So, install a tool grip editor plugin, which you can find in the Roblox Library, and use it to move and rotate the tool as much as you need. If you want the tool to be given to the player at the start of the game, put the tool into StarterPack. Otherwise, put it into ServerStorage.

MarketPlaceService

MarketPlaceService is a service used to handle gamepasses for extra bells and whistles in the game. Let's say I wanted users to get a sword if they have the gamepass.

Creating the Tool

Create the tool like you did in the previous section, and place it into ServerStorage. You can find a sword Model in the Toolbox.

Creating the Gamepass

If you haven't already, publish your game to Roblox. It doesn't need to be public, but it can if you want to. Then, go to the game's page on the website, then go to the Store Tab below the description and add a new gamepass. Give it a name and insert a 150 x 150 pixel image.

If you wish to change the price, click the gear icon and select "Configure". Then, you can change the price. Note that for non-premium users, Roblox will take 90% of Robux earned from gamepasses. For premium users, they will take 30%.

PromptGamePassPurchase()

PromtGamePassPurchase() is a function that asks the player if they want to buy a gamepass. There are two parameters: the player and the AssetId of the gamepass.

local MarketplaceService = game:GetService("MarketplaceService")
local plr = game.Players.LocalPlayer
MarketplaceService:PromptGamePassPurchase(plr,9382042)

Of course, you will need to replace the number with the gamepass' ID.

PromptGamePassPurchaseFinished

This is an event that fires when the player either buys the gamepass or dismisses the popup. It has three parameters: the player, gamepass ID, and whether or not the player purchased the gamepass.

local MarketplaceService = game:GetService("MarketplaceService")
MarketplaceService.PromptGamePassPurchasedFinished:Connect(function(plr,ID,wasPurchased)
    if wasPurchased == true then
         if ID == 3920472 then
              local Sword = game.ServerStorage.Sword:Clone()
              Sword.Parent = plr.Backpack
         end
     end
end)

The first if statement checks whether or not the player purchased the gamepass. The second one checks if the gamepass the player purchased was the one that intended to give the player a sword.

Animation

An animation is a way to make a model move smoothly to make a dance, wave, or whatever.

Creating the Animation

To do this, go to the Plugins Tab and select "Build Rig." Depending on what body type you want, to animate, select a rig that works best for your animation. An R15 model is a model with 15 body parts, and an R6 model is a model that has 6 parts. Choose how many joints you would want to use. The rig should appear in your Workspace.

Then, open the animation editor and use the Select Tool to select the rig. With the animation editor, you can rotate the rig at certain keyframes however you want.

When you are done, click on the animation name and click "Export." Parented to the rig in the Explorer Window, you should see an object with the animation name and a blue square icon. Right click it and choose "Export to Roblox." It will be an asset in your player inventory. Note that R6 animations will not work with R15 models, and vice versa.

Then, copy and paste the AssetId.

Scripting the Animation

Now it is time to animate the character. Insert a script into the character you want to animate, then an animation object into the script. Enter the AssetId of the animation under the AnimationId property of the animation object. Enter the following into the script:

local animation = script:WaitForChild("Animation")
local humanoid = script.Parent:WaitForChild("Humanoid")
local LoadedAnimation = humanoid:LoadAnimation(animation)
LoadedAnimation:Play()

Again, WaitForChild yields until the object exists and has been loaded. LoadAnimation prepares the animation to be played. Finally, Play() will make the animation play.

TeleportService

Sometimes you find that in larger projects, the world just gets a little too big for its own good. So, you can have several separate places in the game. If you struggle to understand what this means, it is like the Pro Towers servers in Tower of Hell. It's still the same game, but it's in a different place.

To do this, make sure your game is published. It can be private.

Then, go to the View tab and open the Game Explorer window. Then, hover over "Places" and click the plus sign to create a place. Right click the place tab in the Game Explorer to copy the PlaceId.

Let's make a teleportation pad that transports people between places. Insert a part into the Workspace and a script inside.

local TeleportService = game:GetService("TeleportService")
local debounce = false

script.Parent.Touched:Connect(function(hit)
     if debounce == false then
           debounce = true
           wait(2)
     end
end)

So far, everything is quite self-explanatory. Make sure that you use a debounce. Otherwise, the user's server will stop responding.

So, set up a local variable to get the player object. Then, use the Teleport() function to insert the script. The first parameter is the PlaceId, and the second parameter is the player object.

local TeleportService = game:GetService("TeleportService")
local debounce = false

script.Parent.Touched:Connect(function(hit)
     if debounce == false then
           debounce = true
           local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
           TeleportService:Teleport(29403734,plr)
     end
end)

Note that this will not work inside Roblox Studio. If you wish to test this go to a live server.

Regions

A region is a 3-dimensional space in the Roblox world. Let's try to find parts in a specific space. Create a part and scale it so that it covers the entire region. Then, try to find the coordinates of the bottom left corner of the part. Do the same with the top right corner. In other words, find the part's minimum and maximum X, Y and Z values. You can now delete a part. Insert this script into the Workspace:

local reg = Region3.new(Vector3.new(minX,minY,minZ),Vector3.new(maxX,maxY,MaxZ))

Replace the six placeholders with coordinates. The variable reg will create a new region with those coordinates.

Threads

What is a Thread?

A thread is a way for a script to run more than one piece of code at a time. So, if I wanted to make two while loops run at the same time with different intervals, it would only fire the topmost loop.

while true do
    print(1)
    wait(2)
end

while true do --Will not work.
    print(2)
    wait(2)
end

This is because the code will be stuck forever in the first while loop.

A thread will allow the same script to run them both at once.

Spawn() Function

The Spawn function allows you to create a new thread.

spawn(function()
   while true do
         print(1)
         wait(1)
    end
end)
while true do
   print(2)
   wait(2)
end

Here, the code will fire both while loops at the same time.

Delay() Function

The Delay function works the same way that Spawn works, only it will create a delay before creating the thread.

delay(5, function()
   while true do
         print(1)
         wait(1)
    end
end)
while true do
   print(2)
   wait(2)
end

Here, the script will fire the second while loop, wait 5 seconds then fire the first while loop.

Coroutines

Coroutines are basically ways to create new threads, only with more functions.

local ctine = coroutine.create(function()
    while true do
         print(1)
    end
end)

Note that the thread will not run without a resume function afterwards.

coroutine.resume(ctine)

You can use the yield function to pause the coroutine.

coroutine.yield(ctine)
wait(1)
coroutine.resume(ctine)

Here, the script will pause the coroutine, then resume it in 1 second.