Efficient way to detect what letter/word the player is currently hovering over

I want to achieve a system where I can effectively tell what word/letter the player is hovering over, because I want to display a certain information when they do

I have looked through devforum for potential solutions so far but they do not meet my liking, the best workaround that I can do is making each individual word/letter be their own textlabel, and that is not really performant

Here is the effect I am looking for to implement

Any help appreciated!

Honestly, I can’t really think of a way apart from splitting the text into several TextLabels. If you want to implement that hyperlink system, it’d be best to use a separate TextLabel just for those special words. That way, you’d only have a few TextLabels and not have one for every word.

1 Like

You could make your own system like TextLabel (with that feature you mention in your post) using throught imagelabels or use Text+ (Resource, which uses imagelabels) you could make like when that imagelabel is hovered change it to whatever your idea was it for

Looking at your example, it doesn’t look like that’s off the one letter. The underline shows it’s the whole word (word combo), like an old hypertext routine leading to a popup on hover.

Roblox doesn’t support real hypertext, but you can mimic it in a TextLabel or TextButton using RichText and a hover.

Quick example:

--LocalScript in StarterPlayerScripts
local plr = game.Players.LocalPlayer
local gui = Instance.new("ScreenGui", plr:WaitForChild("PlayerGui"))

local text = Instance.new("TextButton")
text.Size = UDim2.new(0, 300, 0, 50)
text.Position = UDim2.new(0.5, -150, 0.5, -25)
text.BackgroundTransparency = 1
text.Text = '<u>Hover here for info</u>'
text.RichText = true
text.TextColor3 = Color3.fromRGB(0, 102, 255)
text.Font = Enum.Font.SourceSansBold
text.TextSize = 24
text.Parent = gui

local popup = Instance.new("TextLabel")
popup.Size = UDim2.new(0, 250, 0, 80)
popup.Position = UDim2.new(0.5, -125, 0.5, 40)
popup.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
popup.TextColor3 = Color3.new(0, 0, 0)
popup.TextWrapped = true
popup.Visible = false
popup.Text = "Simulated hypertext popup"
popup.Parent = gui

text.MouseEnter:Connect(function()
	popup.Visible = true
end)

text.MouseLeave:Connect(function()
	popup.Visible = false
end)

I wanted it to be generative as I don’t think setting button positions manually for over 100 keyword is an ideal solution

Sure it is, be creative. One routine does the work generically.
Set up the data and point it the right way for each.

This isn’t the finale script it’s just what would end up part of the core routine.
(with some major tweaking)

Even those old hypertext routines didn’t actually go off the text; they just set the order and jumped to where to drop down on the page to see the information. At some point, someone added a jump to a different page, and the modern “link” was created along with the modern internet.

Ya, it all came from hypertext used for docs, and someone being creative.

Uh again, not really, I’m planning to add this hover effect in regards to status effects (which basically almost every entity applies and my game have atleast 300+ unique entities)

Having to position the hover-buttons manually would not work as it will take too much time and can be ruined by a simple change in wording, again, I am looking for a generative solution over manual-band aid

Hypertext. (more or less)

--LocalScript in StarterPlayerScripts
local Players = game:GetService("Players")
local plr = Players.LocalPlayer
local gui = Instance.new("ScreenGui", plr:WaitForChild("PlayerGui"))
gui.ResetOnSpawn = false

local paragraph = [[
You can use fire or ice and even lightning on the battlefield.
Always beware of poison as that can stack up if used many times.
You may have to heal even if you cure the effect.
]]

local keywords = {
	fire = "Burns target",
	ice = "Slows target",
	lightning = "Shocks target",
	poison = "Deals damage over time",
	heal = "Restores health"
}

local popup = Instance.new("TextLabel")
popup.Size = UDim2.new(0, 250, 0, 80)
popup.BackgroundColor3 = Color3.new(1,1,1)
popup.TextColor3 = Color3.new(0,0,0)
popup.TextWrapped = true
popup.Visible = false
popup.Parent = gui
popup.ZIndex = 2

local paragraphFrame = Instance.new("Frame", gui)
paragraphFrame.Size = UDim2.new(0, 550, 0, 100)
paragraphFrame.Position = UDim2.new(0.5, -300, 0.25, -100)
paragraphFrame.BackgroundTransparency = 1
paragraphFrame.ClipsDescendants = true

local lineHeight = 30
local spaceWidth = 6
local x, y = 0, 0

for word in paragraph:gmatch("%S+") do
	local temp = Instance.new("TextLabel")
	temp.Text = word
	temp.Font = Enum.Font.SourceSansBold
	temp.TextSize = 24
	temp.BackgroundTransparency = 1
	temp.Parent = paragraphFrame
	local size = temp.TextBounds
	temp:Destroy()

	if x + size.X > paragraphFrame.AbsoluteSize.X then
		x = 0
		y = y + lineHeight
	end

	local wLabel = Instance.new("TextLabel")
	wLabel.Text = word
	wLabel.Font = Enum.Font.SourceSansBold
	wLabel.TextSize = 24
	wLabel.BackgroundTransparency = 1
	wLabel.TextColor3 = Color3.new(0,0,0)
	wLabel.Size = UDim2.new(0, size.X, 0, size.Y)
	wLabel.Position = UDim2.new(0, x, 0, y)
	wLabel.Parent = paragraphFrame

	local cleanWord = word:gsub("%p","")
	if keywords[cleanWord] then
		wLabel.TextColor3 = Color3.fromRGB(0, 102, 255)
		wLabel.MouseEnter:Connect(function()
			popup.Position = UDim2.new(0, wLabel.AbsolutePosition.X, 0, wLabel.AbsolutePosition.Y + wLabel.AbsoluteSize.Y + 5)
			popup.Text = keywords[cleanWord]
			popup.Visible = true
		end)
		wLabel.MouseLeave:Connect(function()
			popup.Visible = false
		end)
	end

	x = x + size.X + spaceWidth
end

That was crazy hard to get that lined up where I wanted it to be. It’s going to need some love to make the popups look a bit better. At least it’s a starting point. The box size needs to be considered when putting in the paragraph. set:

paragraphFrame.BackgroundTransparency = 1

to 0 so you can see how it fits for adjustments.

Good luck.