5.8 Working with the UI

User interface (UI or GUI) and user input are two systems that are highly centered around events, both of which you will be working a lot with.

Let’s learn how to create and script a basic GUI that can handle user input. We’ll also learn how to make a GUI pop up on the user’s screen.

The ProximityPrompt is a floating, interactive prompt that shows up when the user approaches its parent element, such as a part. For this, we will use a ProximityPrompt to give the user the GUI.

But first, let’s design a GUI to display an image and have a text input along with a button to submit the text. We will then print that text to the output.


In the StarterGui service, add a ScreenGui object.

The ScreenGui itself is not a visible element but serves as a container for other GUI objects and determines where in the game GUI objects are displayed. As the name implies, ScreenGuis render those objects onto the player’s screen overlay and may contain several ScreenGui’s stacked atop each other.

The ‘DisplayOrder’ property on the ScreenGui determines the order in which each ScreenGui along with its child GUI objects are drawn and therefore, which one’s appear on top.


The two other GUI containers are the BillboardGui, which renders GUI objects as a floating element in the 3D game world, similar to the floating name above a character’s head.

And the other is the SurfaceGui, which renders GUI objects onto the surface of a part. This might be something like a store sign in a game.


GuiObjects are what you actually see on screen. But like the ‘Instance’ and ‘BasePart’ classes, this is a base class for other GUI classes so it cannot be created but instead, comes in the form of frames, buttons, labels and the like.

Add a Frame to the ScreenGui you just created. This should show up as a blank white square in the top left hand corner of the screen.

Frames don’t have a lot of functionality on its own but useful as a container for organizing, placing, and sizing other GuiObjects.

Because the size and position of GuiObjects are set relative to its parent container, this means that GuiObjects parented directly to the ScreenGui will shift around for different screen sizes and aspect ratios. GuiObjects parented to a Frame generally make readjustment simpler.

GuiObject placement and size are determined by the UDim2 datatype which consists of two parts.

A scale dimension. This set set the size/position of the object relative to its parent. So a scale of 0.5 would make the object 0.5 the size of its parent in that dimension.

The second is an absolute dimension. This is in pixels and sets the size or position the object independent of its parent.

Both together determine the final size and position of the GUI object.

We want the frame to be right in the center of the screen. To do that, set the Frame position to 0.5 scale for both the X and Y dimensions.

This will move the frame somewhere near the center. However, it is still not quite centered. That’s because of where the frame’s origin is placed.

By default, the origin is set to the top left corner of the frame. This means setting the frame scale position to 0.5 places the top left corner of the frame at that position.

The ‘AnchorPoint’ property determines where the origin of a GuiObject is—also represented as a scale.

Set the anchor to (0.5, 0.5) which should now center the frame one the screen.

For the size, set it to something suitable on your screen that will fit a small image, a text box, and a button.

I set mine on ((0.5, 50),(0.3, 100)) which makes the frame 1/2 the width of the screen plus 50 pixels and 1/3 the height of the screen plus 100 pixels.

I also set the frame background transparency to 0.5 so I can see the borders of the other GuiObjects.

Now add a TextBox, TextButton, and an ImageLabel to the frame. Position and size them….somewhere.

This is just to demonstrate the usage of each object, so you may decorate, size, and position them as you wish.


For the ImageLabel to display an image, you will need to set the ‘Image’ property to an asset ID of that image you wish to display. You can find images from the Toolbox or upload your own image to your Roblox account.

To do this, navigate to your Roblox account. Then go to Creator Dashboard -> Creations -> Development Items -> Decals -> Upload Asset.

Click on ‘Upload’ and find your image. After the image has been uploaded, return to the ‘Decals’ page. Hover over the icon for the newly loaded image, click on the three dots and ‘Copy Asset ID.’ If you click onto the configuration page for that image, you can also just copy the ID directly from the URL of your browser.

For this demo, I’m using ‘rbxassetid://3203186317,’ which can be found in the toolbox.

The TextBox handles text input, allowing players to type strings into it. Each input generates an event which you can attach a listener.

In this demo, we will only listen for an event when the TextButton is clicked.


Because these are client side GUIs, we will use a LocalScript to handle GUI interaction.

LocalScripts will run if it is a descendant of the Backpack, PlayerGui, PlayerScripts service, or the character. To keep everything under the same container and make it easy to reference the ScreenGui, add a LocalScript directly into the ScreenGui.

This script will execute when the ScreenGui is parent to the PlayerGui.

Lua
--/ScreenGui/LocalScript

local screenGui = script.Parent
local frame = screenGui:FindFirstChild("Frame")
local textBox = frame:FindFirstChild("TextBox")
local textButton = frame:FindFirstChild("TextButton")

local exitString = "exit"

textButton.Activated:Connect(function()
	local inputString = textBox.Text
	textBox.Text = ""
	
	print(inputString)
	
	if inputString == exitString then
		screenGui:Destroy()
	end
end)

Since we’re only interested in capturing the text once the use hits the button, we’ll listen for that event and then print it to the output.

A GUI can be exited by reparenting it elsewhere or destroying it.

In our case, we listen for some string pattern, ‘exit’ in this case, and destroy the ScreenGui if there is a string match.


Because we don’t want the ScreenGui to be immediately copied into the player’s GUI when they enter, move the entire ScreenGui into ReplicatedStorage.

We’ll then use a server side script to place the ScreenGui into the PlayerGui when they activate the prompt.

First, place a part in the workspace. If you already have other parts named “Part” in the workspace, be sure to rename this new part something else and adjust that in the script as well.

Then add a ProximityPrompt to the part and set the ‘HoldDuration’ to 1. This will set the trigger to activate after the user has held the prompt button for 1 second.

Add a script into ServerScriptService.

Lua
--/ServerScriptService/Script

local part = game.Workspace.Part
local proximityPrompt = part:FindFirstChildWhichIsA("ProximityPrompt")
local screenGui = game.ReplicatedStorage:FindFirstChild("ScreenGui") --Find by name

proximityPrompt.Triggered:Connect(function(player)
	local newGui = screenGui:Clone()
	newGui.Parent = player.PlayerGui
end)

This references the prompt and connects to the Triggered event to add the ScreenGui into the PlayerGui.

We want to keep the original in order to make copies for subsequent requests so rather than giving it directly to the player, we call the Clone method to make a copy and give that to the player.

Since all of its child elements are also cloned, the LocalScript we created earlier will correctly reference the new ScreenGui.