How to Activate a Button as being in BillboardGUI?

Hello there, how are you?

Recently, I have been seeing a few games created by well-known developers and one of the things that quite made me feel interested to know is the mechanic to activate a button!

While most of the experiences are common to have the possibilities to interact with objects and/or NPCs (Non-Player Characters) using the feature ClickDetector or ProximityPrompt, there is a specific who uses an ImageLabel via BillboardGUI:

(Photo taken in the Roblox experience “Roliday 2022”)

As analysing, it appears that it uses the UserInputService feature while possible to detect the button in a magnitude… However, I might be wrong in this “theory” of mine. Overall, I am wondering if anyone knows how to do this on Roblox Studio

If anyone is able to help me with this tiny puzzle, I would appreciate it a lot!

Thank you

I think your theory would be correct, how I would do this is have some way to identify 3d instances as being unique “prompt” items, like ProximityPrompts.

Then do magnitude checks to get the closest prompt, and display it. Then you can have an InputBegan event that checks if there is a prompt visible to you/selected and call a function/callback to trigger the prompt.

1 Like

While you could be correct there are multiple ways of doing it, one being the one you theorized, and another one I seemed to remember is using the MaxDistance propriety of a BillboardGui, this changes the maximum distance in studs a billboard can be from the camera and get drawn (via Roblox’s Creator Documentation) and using UserInputService (documentation) you can detect when the player presses E and only run a script if the billboard is getting rendered (documentation).

2 Likes

You can use an billboard gui and check the magnitude between the player and the object.
For example

Rs.RenderStepped:Connect(function()
   if (PlayerRootPart.Position - Obj.Position).Magnitude < 15 then
   billboardGui.Enabled = true
 else
   billboardGui.Enabled = true
   end
end)

--UserInput stuff
--check if is in radius
--furthermore process
1 Like

You could use individual Client scripts (script with client runcontext) in each pedestal and have it check the proximity of the localplayer and the model whenever the user presses “E”. If they are within proximity, execute action. Otherwise, do nothing.

As for the billboardgui, you could use what dianielhoteaale mentioned

@aliaun125 & @Danielhoteaale I have tried creating a script following both contexts, and it appears that while creating one as LocalScript via StarterPlayerScripts, it seemed that it could not detect the HumanoidRootPart:

→ StarterPlayerScripts

-- Player Property

local Players = game:GetService("Players")

local Player = Players.LocalPlayer

local Character = Player.Character or Player.CharacterAdded:Wait()

if not (Character) then
	return
end

local HumanoidRootPart = Character:FindFirstChildOfClass("HumanoidRootPart")

if (HumanoidRootPart) then
	print("True")
elseif not (HumanoidRootPart) then
	return
end

-- Billboard Property

local Sign = game.Workspace.Sign

local BillBoard = game.Workspace.Sign.Text.BillboardGui

local Button = BillBoard.Button

-- Services' Property

local UserInputService = game:GetService("UserInputService")

local RunService = game:GetService("RunService")

-- Message Property In-Screen

local ScreenGUI = Instance.new("ScreenGui", game.StarterGui)

local Frame = Instance.new("Frame", (ScreenGUI))

local Text = Instance.new("TextLabel", Frame)

local Information = {
	ScreenGUI.Enabled == false,
	Frame.Visible == true,
	Frame.Size == UDim2.new(1,0,1,0),
	Frame.BackgroundColor == Color3.new(0,0,0),
	Frame.BackgroundTransparency == 0.5,
	Text.Size == UDim2.new(1,0,1,0),
	Text.BackgroundTransparency == 1,
	Text.Text == "This is a sign",
}

UserInputService.InputBegan:Connect(function(input)
	BillBoard.Enabled = false
	
	if input.KeyCode == Enum.KeyCode.E then
		local Magnitude = (HumanoidRootPart.Parent - Sign.Text.Position).Magnitude
		print(Magnitude)
		
		if (Magnitude) <= 25 then
			BillBoard.Enabled = true
			print(BillBoard.Enabled)
			
			ScreenGUI.Enabled = true
			print(Text.Text)
		end
	end
end)

As the result, I tried creating another one as a normal Script via Workspace with a few changes… Instead of detecting HumanoidRootPart, it would detect UpperTorso. However, the result was printing issues stating that I am attempting to search for a nil value in the local variable called “Character”:

→ Script

-- Player Property

local Players = game:GetService("Players")

local Player = Players.LocalPlayer

--local Character = Player.Character or Player.CharacterAdded:Wait()

--if not (Character) then
--	return
--end

local UpperTorso = Player.Character:FindFirstChild("UpperTorso")

if (UpperTorso) then
	print("True")
elseif not (UpperTorso) then
	return
end

-- Billboard Property

local Sign = game.Workspace.Sign

local BillBoard = game.Workspace.Sign.Text.BillboardGui

local Button = BillBoard.Button

-- Services' Property

local UserInputService = game:GetService("UserInputService")

local RunService = game:GetService("RunService")

-- Message Property In-Screen

local ScreenGUI = Instance.new("ScreenGui", game.StarterGui)

local Frame = Instance.new("Frame", (ScreenGUI))

local Text = Instance.new("TextLabel", Frame)

local Information = {
	ScreenGUI.Enabled == false,
	Frame.Visible == true,
	Frame.Size == UDim2.new(1,0,1,0),
	Frame.BackgroundColor == Color3.new(0,0,0),
	Frame.BackgroundTransparency == 0.5,
	Text.Size == UDim2.new(1,0,1,0),
	Text.BackgroundTransparency == 1,
	Text.Text == "This is a sign",
}

UserInputService.InputBegan:Connect(function(input)
	BillBoard.Enabled = false

	if input.KeyCode == Enum.KeyCode.E then
		local Magnitude = (UpperTorso.Parent - Sign.Text.Position).Magnitude
		print(Magnitude)

		if (Magnitude) <= 25 then
			BillBoard.Enabled = true
			print(BillBoard.Enabled)

			ScreenGUI.Enabled = true
			print(Text.Text)
		end
	end
end)

image

u can load the character properly in an local script

local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local root = char:WaitForChild("HumanoidRootPart")
print(root)  --prints HumanoidRootPart

After testing out the scripts multiple times and analysing what I can improve to be a little bit expected from the sample of the main topic, I decided to put some if statements, and new variables that are tables and loops while printing the HumanoidRootPart’s position as the “magnitude”:

-- Player Property

local Players = game:GetService("Players")

local Player = game.Players.LocalPlayer

local Character = Player.Character or Player.CharacterAdded:Wait()

if not (Character) then
	return
end

local Humanoid = Character:WaitForChild("Humanoid")

if (Humanoid) then
	print(Humanoid)
end

local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

if (HumanoidRootPart) then
	print("True")
	print(HumanoidRootPart)
elseif not (HumanoidRootPart) then
	return
end

-- Billboard Property

local Sign = game.Workspace.Sign

local BillBoard = game.Workspace.Sign.Text.BillboardGui

local Button = BillBoard.Button

-- Services' Property

local UserInputService = game:GetService("UserInputService")

local RunService = game:GetService("RunService")

-- Message Property In-Screen

local ScreenGUI = Instance.new("ScreenGui", game.StarterGui)

local Frame = Instance.new("Frame", (ScreenGUI))

local Text = Instance.new("TextLabel", Frame)

UserInputService.InputBegan:Connect(function(input)
	BillBoard.Enabled = false
	BillBoard.MaxDistance = 25
	
	local Information = {
		ScreenGUI.Enabled == false,
		Frame.Visible == true,
		Frame.Size == UDim2.new(1,0,1,0),
		Frame.BackgroundColor == Color3.new(0,0,0),
		Frame.BackgroundTransparency == 0.5,
		Text.Size == UDim2.new(1,0,1,0),
		Text.BackgroundTransparency == 1,
		Text.Text == "This is a sign",
		Text.Visible == true,
	}
	
	
	local NumbersPossible = {20, 25}
	
	local Magnitude = (HumanoidRootPart.Position).Magnitude
	
	while true do
		task.wait(2.75)
		print(Magnitude)

		if (Magnitude) ~= NumbersPossible[1] and NumbersPossible[2] then
			BillBoard.Enabled = true
		end
		break
	end
	
	if input.KeyCode == Enum.KeyCode.E then
		print(Magnitude)
		
		while (Magnitude) do
			task.wait(5)
			print(Magnitude)
			
			if (Magnitude) <= NumbersPossible[1] and NumbersPossible[2] then
				BillBoard.Enabled = true
				print(BillBoard.Enabled)

				ScreenGUI.Enabled = true
				print(Text.Text)
			elseif (Magnitude) >= NumbersPossible[1] and NumbersPossible[2] then
				print(Magnitude)
				BillBoard.Enabled = false
				print(BillBoard.Enabled)
				ScreenGUI.Enabled = false
			end
			break
		end
	end
end)

You can quite get confused while two loops prints the same statement, yet overall, it works!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.