DefaultOverheads - a familiar overhead Gui system

DefaultOverheads

Screenshot 2023-12-05 213909 Screenshot 2023-12-05 212236


I won’t spend as much time as usual explaining things or decorating the post, since my resources don’t generate much interest most of the time.

This system looks and behaves exactly like the default Roblox overhead (display name), to a T, I checked every pixel and (I think) every scenario. But it has all the benefits of having a Gui you can access: rich text (enabled by default), changing colors, adding gradients, and so on. A bonus is that NPC overheads hide properly (when obstructed), while the default ones don’t.

DOWNLOAD: DefaultOverheads.rbxm (14.8 KB)

I still can’t publish packages to the marketplace for some reason, it is what it is, you can “watch” the topic if you’re interested in updates.

I made it very out-of-the-box, you can just put the ModuleScript inside ServerScriptService and it will replace all default overheads. It also does cleanup in regard to the Guis, but it does not clean up Player/Character connections, which you should be destroying yourself.


I will explain only basic usage, for anything beyond that feel free to ask:

Screenshot 2023-12-05 214158

That’s the script of interest.

image

You may, of course, require it from elsewhere if needed.

Here is a basic example:

local DefaultOverheads = require(script.Parent)

DefaultOverheads.OnAdded:Connect(function(OverheadGui)
	
	if not OverheadGui.Player then -- NPC
		return
	end
	
	local DisplayName = OverheadGui:GetTag('DisplayName')
	DisplayName.Text = '⭐'  .. DisplayName.Text .. ' ⭐'
	
	-- an example of connecting to the Player
	local Level = OverheadGui:AddTag('Level', '')
	local leaderstats = OverheadGui.Player:WaitForChild('leaderstats') -- if you're sure it will be added
	
	leaderstats.Level.Changed:Connect(function(level)
		Level.Text = 'level: ' .. level
	end)
	
	Level.TextSize = 32
	Level.Text = 'level: ' .. leaderstats.Level.Value
	
	-- an example of connecting to the Character
	local Hurt = OverheadGui:AddTag('Hurt', '')
	local Humanoid: Humanoid = OverheadGui.Character:WaitForChild('Humanoid') -- if you're sure it will be added

	Humanoid.HealthChanged:Connect(function(health)
		Hurt.Text = health < Humanoid.MaxHealth and 'HURT' or ''
	end)
	
	Hurt.FontFace = Font.fromName('Jura', Enum.FontWeight.Bold)
	Hurt.TextColor3 = Color3.new(1, 0.25, 0.25)
	Hurt.Text = Humanoid.Health < Humanoid.MaxHealth and 'HURT' or ''
	
end)

To see the results (without having to invite someone else), either find the BillboardGui inside your Character, and clear the PlayerToHideFrom property, or add the overhead to a Dummy/NPC.

And here is a basic overview of the two modules (server-side that is):

DefaultOverheads

 function DefaultOverheads.Add(Character: Model, Adornee: BasePart): OverheadGui

Creates a new OverheadGui. This is done automatically for all Player Characters, you only need to use it for NPCs. Adornee is required for now, use the Head for default look. It doesn’t have to be an R15 or R6 Character/Model though, nor does it need to have a Humanoid, it can be anything.

returns OverheadGui object (more on that below), not the BillboardGui Instance

 function DefaultOverheads.Get(Character: Model): OverheadGui?

returns OverheadGui object of a Character/Model (if it exists); again, not the BillboardGui Instance

 function module.OnAdded:Connect(func: (OverheadGui: OverheadGui) -> (), ignoreExisting: true?): Connection

OnAdded is a fake signal, just a holder for :Connect to which you provide a function which will be called every time a new OverheadGui is created. The function will also be called for every existing OverheadGui unless ignoreExisting is true. To avoid the possibility of missing any of the automatically created ones, don’t use this unless you know why you’re using it.
returns a fake connection that can be :Disconnect()-ed

OverheadGui

OverheadGui.Character: Model
OverheadGui.Player: Player?

Self-explanatory. These are there so you don’t have to combine this module with other code too much, but can instead access the Character/Model and Player (if any) directly, for the purpose of adding and modifying tags.

function OverheadGui:AddTag(name: string, text: string, index: number?): TextLabel

Creates a new “tag” - that is, a TextLabel which you can then modify directly.
name is used as an identifier. If a tag with the same name already exists, it will be removed; the new one will inherit it’s position (layout order)(if index is not provided) but nothing else. Sometimes you might want this, but most of the time you’ll want to modify the existing tag.
text is self-explanatory
index is an optional number to push the tag to a specific position (vertically). If not provided, the tag will go on top of the existing ones. Tags are indexed bottom-to-top.

A “DisplayName” tag is created by default for Player Characters and NPCs alike. It’s text will be either the Player.DisplayName, or the name of whatever Instance you used to create the OverheadGui if there is no associated Player.

returns TextLabel

function OverheadGui:GetTag(name: string): TextLabel?

Primarily for modifying the premade “DisplayName” tag.

returns TextLabel (if it exists)

To remove a tag you can :Destroy() it, it’s safe. :Destroy()-ing the BillboardGui is also safe.


That's it! That's the basic overview. There are more things to be said, I haven't even mentioned the client side of things, but the average user wouldn't be interested. If you are, again: ask away.

There are also things that are tucked away (there, but won’t show up in auto-complete) so the average user won’t be tempted. You can look through the code (or ask) if you want to access something specific.

As for upgrades, client options are one possibility - e.g. toggling visibility for all overheads, as well as your own, setting the display distance, adding a scale multiplier, and so on. Recreating the health bar is also an option, integrating images, adding helper functions for gradients…

If there’s enough interest in the community, I can do some/all of these things, and/or other things… whatever is requested most.

Almost forgot… performance… should be fine. I got an average of ~1ms for 64 dummies, most of which were in range (which then requires a raycast).

32 Likes

nice work, going to use this in my game!

I’m curious as to how you’ve shifted/recreated Roblox’s overhead text. Nice resource though

Thanks! Let me know what you think, if you’d like to see something added, or if you run into any issues.

What about it exactly? For the UI part itself you can check this out:

image

As for the behavior, in brief, the scale is changed as follows (distance between camera position and target):

  • distance < 20 studs: scale = 1
  • distance < 50 studs: scale = 0.75
  • above: scale = 0.5

And the transparency it is calculated from the local NameDisplayDistance and the current distance of the viewer (think Head.Position) from the target, in this way:

  • distance < NameDisplayDistance * 0.9: transparency = 0
  • NameDisplayDistance * 0.9 < distance < NameDisplayDistance: transparency = 0-1 (linear)

Additionally the overhead is hidden if that distance exceeds NameDisplayDistance, or if there’s something in between the camera and the target, except the stuff that’s filtered out on the client (anything that an overhead was added to is filtered out automatically, like Characters).

The target position is always Adornee.Position + (0, 1.5, 0) which is the offset of the UI, and viewer position is either local character Head.Position or Camera.Focus.Position if Head is not available, plus (0, 1.5, 0). I’ll backtrack and say that I’m not 100% sure this is 100% accurate, but lets say it’s at least 99% accurate :clown_face:
If there’s enough interest to warrant an update, I’ll come back to it to make sure.

2 Likes

Very nice module, thank you for that!

Some options for scaling and display distance would be nice :slight_smile:
The automatic scaling can currently be a bit “twitchy” when you enable the BillboardGui on your own player (yes, I know this is normally hidden so maybe this is off topic) and in a certain zoom distance, the overhead gui kind of bounces between two sizes as you run with your character.

If the sizing change have to be programmatic, maybe try to tween it for a smoother transition? Just an idea!

All in all, great work!

Thanks for the feedback, glad you like it :slight_smile:

I do believe I added a DefaultOverheads.SetDisplayDistance(distance: number) on the client. By default it’s StarterPlayer.NameDisplayDistance and then it goes off of LocalPlayer’s Humanoids as they’re added. Check inside the LocalScript; you can either overwrite that logic entirely, or you can make use of that and just change the local Humanoid’s NameDisplayDistance from anywhere. This, as is the default behavior, changes the display distance of all overheads locally. Adding a per-overhead option is doable, if that’s what you wanted?

I agree about scaling, I will add a multiplier option.

Thanks for informing me about the twitch, I can imagine why it happens, and it makes sense why it would only happen on the local one. I’ll try to come up with a fix, but tweening it would make things look less like the default, and I’m not sure how to feel about that, though it does make me wonder. Maybe adding multiple scaling “options” would be the best approach:

  • “default” - default scaling
  • “smooth transition” - like default but transitions are smooth instead of snappy
  • “smooth” - scales smoothly between min and max scale, no transitions

uh i need help w this pronto im confused

I pretty much forgot about this, but how can I help?

Update the Adornee after the player switches characters, as the billboard disappears when the new character has a different head.

Can you please elaborate on “a head other than a badge”?

just the whole thing about it i know where to put it but just how to get it working cause it isnt appearing normally