Easy Access Objects: Reduce itterating through object for variables

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.

local HealthBar =  ObjectService:Get("HUD", "HUD")
10 Likes

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.

3 Likes

I only use it for style based on what the job of the function is.

Not bad, although I tend to make my UIs as static as possible to avoid situations where I need to move stuff.

Also: iterating not itterating :wink:

1 Like

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.

If direct indexxing is a problem then why would local variables not solve it

1 Like

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.

1 Like

this = that
this = that.that
this = that.that
this = that.that.that
this = that…

You get the point, it just reduces the need to repeat this and oh look that #2 was moved somewhere else, time to change everything that pointed to it.

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.

9 Likes