Just sharing something that I started doing for months now that’s save me a lot of time working with objects with a large hierarchy and the iteration for variables becomes a absolute mess. This was mainly done to reduce the work on UI variables.
How does it work?
Every descendant is stored within a table and assigned and accessible via name.
The storage dictionary in the table is made based off the main objects name.
Downside?
You need to have unique names for the table or it will be overwritten.
Does not watch for new descendants to add them to the table (easy to do though).
Module
local Objects = {}
Objects.Directory = {}
function Objects:Get(dir_name, obj_name)
return Graphic.Directory[dir_name][obj_name]
end
function Objects.new(object)
Graphic.Directory[object.Name] = {}
Graphic.Directory[object.Name][object.Name] = object
local Descendants = object:GetDescendants()
for _, descendant in pairs(Descendants) do
Graphic.Directory[object.Name][descendant.Name] = descendant
end
return Graphic.Directory[object.Name]
end
return Objects
Example Use:
Workspace:
PlayerGui
HUD
Stats
Health
HealthBar
Background
Stamina
Standard Method
local HUD = game.Players.LocalPlayer.PlayerGui.HUD
local HealthBar = HUD.Health.HealthBar
Descendant Storage
local ObjectService = require(script.Module)
local HUD = game.Players.LocalPlayer.PlayerGui.HUD
ObjectService.new(HUD)
local HealthBar = ObjectService:Get("HUD", "HealthBar")
This is really only truly useful when you keep moving around objects especially in UI design and have to reconnect the scripts variables each time. If you want the object you ran through the module just reuse it’s name.
One of my major pet-peeves with this style of doing things is the : over . for the Get function when it’s not a method or specifically object oriented (seems stylistic I guess?). Other than that, pretty nice for easy fetching.
This is a nice tool for people who want a quick way to access things, but in the grand scheme of things I personally think it’s better to index objects directly as opposed to using a module to facilitate this. From what I see, this will expand my code beyond a few lines, it’s not easy to keep track of and indexing traditionally feels more useful, you know what I mean?
There are cases in which a variation of this may be useful (i.e. storing Animation track objects in a table for playing later), though I wouldn’t recommend relying on this heavily for any works.
Well I dont actually use this method for anything besides UI because as a UI Designer Im constsntly having to move objects so rescripting for that is frustrating. There and a time and place when its useful or just wasting space. It all depends on how much you expect you’ll need to go back and fix variables.
If you know the game Sunset City, the phone, and saw the UI and how massive it was. You would understand why I prefer this method now.
I suppose it really all boils down to personal preference and comfortability. Even with a phone UI like Sunset City’s, I would still opt for direct indexation.
That’s a good point. A lot of times I find myself moving UI around to make it look better / have minimal GUI objects. I always have to tweak my scripts to work with the updated UI.
It’s worth noting that Roblox supports this method out of the box:
ObjectService.new(HUD)
local HealthBar = ObjectService:Get("HUD", "HealthBar")
is the same as
local HealthBar = HUD:FindFirstChild("HealthBar", true)
just a bit more verbose! The , true) makes it find the first descendant instead of the first child.
I usually just add a small snippet to the beginning of gui scripts that looks like
local function get(name, parent)
return (parent or gui):FindFirstChild(name, true)
end
which lets me later do
local HealthBar = get("HealthBar")
This technique is particularly useful when you’re writing the programming for a work-in-progress, a prototype, or anything that may change structure significantly later. With find-first-descendant code, you can usually keep the names the same and make a few changes to the programming. Without it, you have to make many changes to work with the new structure.
A good analogy is web development. The class and id properties are used all the time in a find-first-descendant manner because navigating the whole tree is usually not reasonable and will not hold up to future changes well. Same principle here.