We use cookies on this site to enhance your user experience

Top Down Action: Dialog

Top Down Action: Dialog

10 min

Some of the keys in our level are far away from the door they open and won’t be on the screen when the player finds them. To give more feedback to the player, let’s create a dialog when a player steps on a key so they know that a door opened.

Creating GUI Elements

To make 2D GUIs in Roblox, we first need need to create a ScreenGui to hold them. A ScreenGui is a type of object called a LayerCollector which holds and displays 2D elements. A ScreenGui draws its objects directly to the screen. Right click on StarterPlayer and insert a new ScreenGui. Rename the ScreenGui to DialogGui.

TDS_Dialog_DialogGui.png

Now that we have a ScreenGui, we need to put something in it to draw. We’ll start with a Frame|Frame, which is simply a bordered rectangle, to use as the background for our dialog. Insert a frame into DialogGui, and rename the frame to DialogFrame.

TDS_Dialog_DialogFrame.png TDS_Dialog_DialogFrame3Dview.png

We now have a white square in the upper left corner of the screen. We need to resize it so that it stretches across the screen. Right now, the GuiObject/Size|Size property of DialogFrame is set to {0, 100}, {0, 100}. These numbers represent the size of the Frame in X and Y. If we just look at X, we can see that it is {0, 100}. The first number is used to scale the frame based on its parent. At the moment it is 0, so it is not scaled at all. The second number is a raw number of pixels to add to the width of the frame. It is currently at 100, so the frame is 100 pixels wide.

Change the GuiObject/Size|Size of DialogFrame to {0.8, 0},{0.2,0}. Notice how this stretches the box. By setting the X scale to 0.8 we’re telling the Frame to always take up 80% of the width of the screen. Likewise, setting the scale of Y to 0.2 tells the frame to take up 20% of the height of the screen.

TDS_Dialog_DialogFrameScaled.png

Now that we have the background frame the size we want, let’s move it over so that it is positioned in the center of the screen. Change the GuiObject/Position|Position property of DialogFrame to {0.1,0,}, {0, 0}. This works similarly to how we scaled the Frame, but instead of setting the size of the frame, it moves the frame away from the upper left corner of the screen. By setting the X scale to 0.1, we are telling the Frame to be 10% of the screen away from the corner.

TDS_Dialog_DialogFramePositioned.png

Thumbnail Image

We will use this dialog for several elements in the game, so let’s add an image to our frame to help the user understand the context of the message. Insert an ImageLabel into the DialogFrame and name it Key, as we will display this when the user picks up a key. The position of the ImageLabel is fine, but let’s resize it so it fills up more of the DialogFrame. Change the size to {0.15, 0},{1, 0}. This makes the ImageLabel take up 15% of the width of the Frame and 100% the height of the Frame.

TDS_Dialog_KeyExplorer.png

We will use an existing Roblox image to put inside our ImageLabel. Select the ImageLabel and enter rbxassetid://320682344 into the ImageLabel/Image|image property. This will insert a thumbnail picture of the key.

TDS_Dialog_Key.png

Now we need something to hold the text we want to display in the dialog. Insert a TextLabel into DialogFrame. Change the Size property of the TextLabel to {0.85, 0},{1, 0} and the Position property to {0.15, 0}, {0, 0}. To make sure the text fills the label, set the TextScaled property to true.

TDS_Dialog_TextExplorer.png TDS_Dialog_Text.png

Hiding Dialog

Now that we have our dialog set up, let’s hide it offscreen so the player doesn’t see it right away. Change the GuiObject/Position|Position property of DialogFrame to {0.1, 0},{-0.2, 0}. Also, set the Visible property of Key to false. Later on in code we will move the DialogFrame and show Key.

Show Dialog

Now we need to trigger our dialog to show when a player steps on key. The first thing we will do is create a RemoteEvent. This type of object allows a script on the server talk to a local script on a client. In this case we want the scripts we added for the doors to be able to tell a local script to display the GUI we just made. Right click on ReplicatedStorage and insert a RemoteEvent. Name the RemoteEvent ShowDialog.

In our DoorScript that we created earlier, let’s add the code to fire this RemoteEvent:

local key = script.Parent.Key
local door = script.Parent.Door
local showDialog = game.ReplicatedStorage.ShowDialog

local function onKeyTouch(otherPart)
	if game.Players:GetPlayerFromCharacter(otherPart.Parent) then
		key:Destroy()
		door.Anchored = false
		door.CanCollide = false
		door.BodyPosition.Position = door.Position + Vector3.new(0,10,0)
		door.Transparency = 0.5
		door.Sound:Play()
		showDialog:FireAllClients('Key', 'Key found, door unlocked', 2)
	end
end

key.Touched:connect(onKeyTouch)

Now when a player steps on a key, the server will tell every client to display a dialog. It won’t work quite yet though, as we do not have any code on the client listening to this event. Let’s create a LocalScript to manage showing and hiding our dialog. Insert a new LocalScript into StarterPlayerScripts, and name it DialogScript. Insert the following code:

local player = game.Players.LocalPlayer
local playerGui = player.PlayerGui
local dialogFrame = playerGui.DialogGui.DialogFrame
local showDialog = game.ReplicatedStorage.ShowDialog

local function onShowDialog(thumbnail, text, duration)
	
end

showDialog.OnClientEvent:connect(onShowDialog)

First we setup variables for various things we need, such as the player, some of our GUI elements, and the RemoteEvent we just created. Then we define the function onShowDialog. This function has three parameters: thumbnail in case we want to show a certain picture, text to set the text that displays, and duration for how long the dialog should show up for. Lastly, we bind onShowDialog to the OnClientEvent of showDialog.

Now let’s add code to handle the parameters of the function:

local player = game.Players.LocalPlayer
local playerGui = player.PlayerGui
local dialogFrame = playerGui.DialogGui.DialogFrame
local showDialog = game.ReplicatedStorage.ShowDialog

local function onShowDialog(thumbnail, text, duration)
	local thumbnailPicture = dialogFrame:FindFirstChild(thumbnail)
	thumbnailPicture.Visible = true
	dialogFrame.TextLabel.Text = text
	
	wait(duration)	
	
	thumbnailPicture.Visible = false
end

showDialog.OnClientEvent:connect(onShowDialog)

When the function is called it will look inside dialogFrame for the name passed in the argument thumbnail. For now, we are just be passing in the name Key to find the image we inserted earlier, but later we will be adding other thumbnails.

Next, the text in the TextLabel is set to the passed in text and the function waits for duration. Last, we hide thumbnail picture.

Animating the dialog

Let’s use animations to show and hide the DialogFrame.

local animationSpeedShow = .5
local animationSpeedHide = .5
local positionShow = UDim2.new(0.1, 0, 0, 0)
local positionHide = UDim2.new(0.1, 0, -0.2, 0)

local player = game.Players.LocalPlayer
local playerGui = player.PlayerGui
local dialogFrame = playerGui.DialogGui.DialogFrame
local showDialog = game.ReplicatedStorage.ShowDialog

local function onShowDialog(thumbnail, text, duration)
	local thumbnailPicture = dialogFrame:FindFirstChild(thumbnail)
	thumbnailPicture.Visible = true
	dialogFrame.TextLabel.Text = text
	dialogFrame:TweenPosition(positionShow, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, animationSpeedShow)
	wait(duration)	
	dialogFrame:TweenPosition(positionHide, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, animationSpeedHide)
	wait(animationSpeedHide)
	thumbnailPicture.Visible = false
end

showDialog.OnClientEvent:connect(onShowDialog)

We first setup variables for the speed of the animations, one for showing and one for hiding. We likewise setup positions for where we want the DialogFrame to be when it is shown and hidden.

In the function we can then use the function GuiObject/TweenPosition|TweenPosition to animate the DialogFrame. The first argument is what position to animate the element to. The second and third arguments determine the easing style of the animation. An easing style allows animations to change speed over time, and the direction determines what point of the animation the easing is applied to. The last argument is how long the animation will take.

Filling in Topbar

You may have noticed that the dialog is still visible under the topbar while the game is running. We can fix this simply by setting the topbar’s transparency to 0 so it is completely opaque:

local animationSpeedShow = .5
local animationSpeedHide = .5
local positionShow = UDim2.new(0.1, 0, 0, 0)
local positionHide = UDim2.new(0.1, 0, -0.2, 0)

local player = game.Players.LocalPlayer
local playerGui = player.PlayerGui
local dialogFrame = playerGui.DialogGui.DialogFrame
local showDialog = game.ReplicatedStorage.ShowDialog

playerGui:SetTopbarTransparency(0)

local function onShowDialog(thumbnail, text, duration)
	local thumbnailPicture = dialogFrame:FindFirstChild(thumbnail)
	thumbnailPicture.Visible = true
	dialogFrame.TextLabel.Text = text
	dialogFrame:TweenPosition(positionShow, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, animationSpeedShow)
	wait(duration)	
	dialogFrame:TweenPosition(positionHide, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, animationSpeedHide)
	wait(animationSpeedHide)
	thumbnailPicture.Visible = false
end

showDialog.OnClientEvent:connect(onShowDialog)

TDS_Dialog_KeyFound.png