Well hello there! You’re probably here for the tutorial, so let’s get started!
THIS TUTORIAL IS UNFINISHED AND WILL BE RELEASED ONTO COMMUNITY TUTORIALS WHEN DONE
What you’ll need to know before you start:
- GUI manipulation.
- Roblox’s client server model
- Context action service
- Tween service
- For loops
- Datastores (optional)
This tutorial should be begginer friendly, except for the optional part, which may be a little bit harder to follow. What we will make is a simple phone gui similar to Watch dogs or other open world games.
What our phone will include:
- Rather easy “app” support
- Changeable main screen (with optional background saving)
- A few basic apps such as maps and utilities (extra)
Step 1) Creating the phone
This will be the first and probably easiest part in the tutorial. It’s up to you how you’ll desgin it. Maybe you want it to look like an android phone. Or apple? Maybe even Arch linux for whatever reason? It’s time to get creative! Don’t worry, I’ll drop my phone’s setup below and also leave a .rbxm file if needed.
My ui looks like this in the tree:
And in game it looks like this:
You can find all the files at the bottom of the tutorial
Step 2) Coding the booting of our phone
But wizard, what do you mean with this? No worries, it’s nothing too hard. We will code an opening part to it. You can use a gui button or context action service. I’ll go with context action service. Why? It does the job well and you can always unbind the function from the service, say in a cutscene.
We’ll need to create a local script, in starter character scripts. I’ll call mine: “OpenPhone”
Now let’s add some text to that script, shall we?
Keep in mind I have disabled the visible property of my “MainContainer” frame
We’ll start with some variables:
local tweenservice = game:GetService("TweenService") --Getting tween service
local contextactionservice = game:GetService("ContextActionService") --Getting ContextActionService
local plr = game.Players.LocalPlayer --Getting our player
local phone = plr.PlayerGui:WaitForChild("Phone") --Getting our phone screen gui from the player's gui folder
local phonemain = phone:WaitForChild("MainContainer") --Getting the container frame
local open = false --This is a boolean value we'll use to keep track of the phone's state
Great! Let’s move onwards! All information needed will be found in the comments.
local function openphone()
--This is the function we'll bind to contextactionservice and it should open the phone
if open == false then --Checking if our phone is open; if not we will set the value to true and open it; else we will set the value to false and close it
phonemain.Visible = true
open = true
else
phonemain.Visible = false
open = false
end
end
Nothing too hard, right? Now off to binding our function!
contextactionservice:BindAction("OpenPhone", openphone, false, Enum.KeyCode.Tab) --Binding the function to the key tab
To unbind it you’d do:
contextactionservice:UnbindAction("OpenPhone") --It's that simple, really. We used the name we gave to our action above to unbind it. You can unbind and bind at any time!
And done! If you followed through, your gui should open when pressing TAB! If not, check your output. You’ll be able to troubleshoot there. It would be best to have a similar phone tree, it does matter.
Result:
Now, we’ll add some extra eyecandy to make it look better! First of all, we’ll add a simple blur effect.
In the function, simply add a blur effect to the camera. Our variable declaration should know look like this:
local tweenservice = game:GetService("TweenService") --Getting tween service
local contextactionservice = game:GetService("ContextActionService") --Getting ContextActionService
local plr = game.Players.LocalPlayer --Getting our player
local phone = plr.PlayerGui:WaitForChild("Phone") --Getting our phone screen gui from the player's gui folder
local phonemain = phone:WaitForChild("MainContainer") --Getting the container frame
local open = false --This is a boolean value we'll use to keep track of the phone's state
local camera = workspace.CurrentCamera --The player's camera
Now for the function we’ll create a new instance using Instance.new(), a blur effect
local function openphone()
--This is the function we'll bind to contextactionservice and it should open the phone
if open == false then --Checking if our phone is open; if not we will set the value to true and open it; else we will set the value to false and close it
phonemain.Visible = true
blur = Instance.new("BlurEffect") --We are creating our blur effect and parenting it to the camera
blur.Parent = camera
open = true
else
phonemain.Visible = false
blur:Destroy() --We are destroying our blur effect
open = false
end
end
Pretty cool, isn’t it?
For our last addition (You can make more yourself, we’ll create a shut down/startup effect using for loops. Let’s goooo!
For this task, I made the welcome screen and apps frame invisible, as well for the descendants of the background image, located in the apps frame. The background is still, visible. Sorry if this is hard to understand. I tried my best explaining this setup. You’ll find all the files you might need if the explanation was too complicated at the end.
We will update our variable declaration by adding the following:
local phoneapps = phonemain.PhoneFrame.Apps.Background --Getting the apps frame
Here is the full declaration, so far:
local tweenservice = game:GetService("TweenService") --Getting tween service
local contextactionservice = game:GetService("ContextActionService") --Getting ContextActionService
local plr = game.Players.LocalPlayer --Getting our player
local phone = plr.PlayerGui:WaitForChild("Phone") --Getting our phone screen gui from the player's gui folder
local phonemain = phone:WaitForChild("MainContainer") --Getting the container frame
local phoneapps = phonemain.PhoneFrame.Apps.Background --Getting the apps frame
local open = false --This is a boolean value we'll use to keep track of the phone's state
local camera = workspace.CurrentCamera --The player's camera
Amazing! Now we’ll update our function, accordingly:
local function openphone()
--This is the function we'll bind to contextactionservice and it should open the phone
if open == false then --Checking if our phone is open; if not we will set the value to true and open it; else we will set the value to false and close it
phonemain.Visible = true
blur = Instance.new("BlurEffect") --We are creating our blur effect and parenting it to the camera
blur.Parent = camera
open = true
phonemain.PhoneFrame.Apps.Visible = true --We'll make the apps and welcome screen visible
phonemain.PhoneFrame.WelcomeTitle.Visible = true
for index, v in pairs(phoneapps:GetDescendants()) do --We are looping through the gui's descendants and making them visible, once the phone "booted up", to achive a sort of lagging that is natural for most OS'es when powered on
if not v:IsA("UICorner") then
v.Visible = true
wait(0.1)
end
end
else
phonemain.Visible = false
blur:Destroy() --We are destroying our blur effect
open = false
phonemain.PhoneFrame.Apps.Visible = false --We'll make the apps and welcome screen invisible
phonemain.PhoneFrame.WelcomeTitle.Visible = false
for index, v in pairs(phoneapps:GetDescendants()) do --We are looping through the gui's descendants and making them invisible, once the phone "shut down"
if not v:IsA("UICorner") then
v.Visible = false
end
end
end
end
We added a for loop at to make every app visible one by one. And another one to make each app invisible one by one, similar how most OSes boot up.
I’ve used if not v:IsA("UICorner") then
to check if the ui element is not an ui corner. If there’s any other instance type that you do not want to be made visible, or is simply impossible to make visible (Example: gradients), simply add them here.
Alright then, you should have something like this by now:
Not so hard after all! Now that our opening up code is finished, we will take care of some basic settings
But before we continue, here is the finished code, if you need to double check:
local tweenservice = game:GetService("TweenService") --Getting tween service
local contextactionservice = game:GetService("ContextActionService") --Getting ContextActionService
local plr = game.Players.LocalPlayer --Getting our player
local phone = plr.PlayerGui:WaitForChild("Phone") --Getting our phone screen gui from the player's gui folder
local phonemain = phone:WaitForChild("MainContainer") --Getting the container frame
local phoneapps = phonemain.PhoneFrame.Apps.Background --Getting the apps frame
local open = false --This is a boolean value we'll use to keep track of the phone's state
local camera = workspace.CurrentCamera --The player's camera
local function openphone()
--This is the function we'll bind to contextactionservice and it should open the phone
if open == false then --Checking if our phone is open; if not we will set the value to true and open it; else we will set the value to false and close it
phonemain.Visible = true
blur = Instance.new("BlurEffect") --We are creating our blur effect and parenting it to the camera
blur.Parent = camera
open = true
phonemain.PhoneFrame.Apps.Visible = true --We'll make the apps and welcome screen visible
phonemain.PhoneFrame.WelcomeTitle.Visible = true
for index, v in pairs(phoneapps:GetDescendants()) do --We are looping through the gui's descendants and making them visible, once the phone "booted up", to achive a sort of lagging that is natural for most OS'es when powered on
if not v:IsA("UICorner") then
v.Visible = true
wait(0.1)
end
end
else
phonemain.Visible = false
blur:Destroy() --We are destroying our blur effect
open = false
phonemain.PhoneFrame.Apps.Visible = false --We'll make the apps and welcome screen invisible
phonemain.PhoneFrame.WelcomeTitle.Visible = false
for index, v in pairs(phoneapps:GetDescendants()) do --We are looping through the gui's descendants and making them invisible, once the phone "shut down"
if not v:IsA("UICorner") then
v.Visible = false
end
end
end
end
contextactionservice:BindAction("OpenPhone", openphone, false, Enum.KeyCode.Tab) --Binding the function to the key tab
--contextactionservice:UnbindAction("OpenPhone") --It's that simple, really. We used the name we gave to our action above to unbind it. You can unbind and bind at any time!
Step 3) Making the settings app.
Why a settings app? How is it helpful?
Well… What if your players wanted to change background like on a real phone? We’ll take care of that on our settings app!
In our local script, which we will use to handle most events (not necesarry, you can change this if you want), we will use a mouse click event to open the settings app. We will make a new frame inside the phone and open it when the button is clicked. Better get creative! This and the map app will serve as “Templates” for your own apps!
Here’s my current phone gui setup. I’ve added the settings app frame under the PhoneFrame:
I’ve got two buttons in my settings interface, one for backgrounds and one for “System information”. The last one is purely cosmetic, I won’t use it.
Alright now that we’re set, hopefully, we can start coding the app.