How to get a specific child table from its parented part?

I’ve got a series of parts, called Plinths, around the map. During the game, they get objects assigned to them, from a class called clTwrs. Later on, I want to check if a particular Plinth has a class assigned or not. The class (a table) has the Plinth as its parent. So, to check if the Plinth has a class, I should just use :GetChildren(). But, :GetChildren() isn’t showing the class as a child.

Here’s the simplified class module and the code that invokes it:

function Twr.new(pPlayer, pTypeStr, pParentPlinth)
	local lNewTwr = {}				-- Will return the new Twr
	setmetatable(lNewTwr, Twr)		-- For making Twr work like a class
	lNewTwr.Name	= "TwrObj"    -- I tried setting .Name to see if that made a printable name to appear in :GetChildren()
	lNewTwr.Player	= pPlayer
	lNewTwr.TypeStr = pTypeStr
	lNewTwr.Parent = pParentPlinth
	return lNewTwr
end

-- and the code the invokes it:
ClTowers = require(game.ReplicatedStorage.clTwr)
local lNewTower = ClTowers.new(lPlayer, "TowerType1", lPlinth)
-- This all works; the tower and all its parts are created by the class module.
-- But
print(lPlinth:GetChildren()) -- does not list the Table which has the Plinth as its parent

-- Trying again, but manually setting parent
local lNewTower = ClTowers.new(lPlayer, "TowerType1", lPlinth)
lNewTower.Parent=lPlinth -- This is done in the class, but double-checking by doing it here too
print(lPlinth:GetChildren()) -- still doesn't list it

Note the line in .new that sets the new object’s parent to the plinth. In case there was a problem with that not working because the object was still in the process of being created, I added a 2nd attempt to set its parent, outside of the .new method. In either case, it doesn’t appear as a child.

How do I get access to the child table using things like :WaitForChild(“put something here to refer to Table”)?

Things that haven’t worked:
(1) Add a Custom Property to a Part. There must be a way to have a custom property of a part, which points to a Table. However, it’s not so easy in Lua. It’s the same problem as Way to link part to a table (object) .

(2) Using an ObjectValue parented to the Plinth; this worked when pointing the OV at a model, and I can use :GetFirstChild(“OVTwrObject”) to get to the Parts, but, doesn’t accept Tables. Why it’s limited to not do that, I’ve no idea. And it’s the Table I need, because it’s got all the state properties.

(3) Using a Config object as a child of the Plinth with a whole load of custom properties. This is how it started, but it doesn’t scale well and is very cumbersome - i.e. I’m writing an entire “this is how you get and set properties” in a class, getting it to create its own Config child objects… it was like creating OOP methods from scratch, which is obviously the wrong path, but what is the right way to simply link a part to its class data?

Hi! Looks like you’re where I was 3 years ago. Let me help…

In my question you linked, I was attempting to do this for a “The Quarry”-style voxel quarry. Each part would store custom values relating to its ore type, health, position in the voxel-grid, etc. I wanted to easily link this data to the part, and this was in an era before Attributes were full-release. What I ended up doing was having a simple function convert 3D coordinates to the voxel coordinates, which would then be used in a table lookup (the voxel grid was kept in a 3D table).

That solution, in hindsight, is pretty bad, but I was fairly young so I’ll excuse it. The reason why I didn’t go with @sjr04’s solution was that it:
a) Didn’t work to begin with, extra_properties was complete ignored. (I tagged him here though incase I’m having a really dumb 4:00 AM moment and am just not understanding it at all).
b) Doesn’t allow you to access extra properties from the Part instance in the world.

Here’s the code, slightly modified to work:

local function wrap_instance(instance, extra_properties)
	extra_properties.self = instance
	return setmetatable(extra_properties, { __index = instance })
end

local part = Instance.new("Part")
part.Parent = workspace
part = wrap_instance(part, { Plunkus = 3 })
print(part.Plunkus)--3
print(workspace.Part.Plunkus)--nonvalid member error

As you can see, workspace.Part.Plunkus doesn’t exist, because the part variable is actually a table in of itself with the Part instance as the __index pointer. You can access all the properties of the part in the script’s scope, PLUS the Plunkus property, but only as long as you keep the table returned by the function in memory. The part doesn’t actually have an extra property.

Assigning a Parent “property” to your clTwr instance doesn’t do anything except create a dictionary index with the key “Parent”. You can read this from the memory address it’s stored at via a local variable, but that can only be done in the script’s scope, not the game’s scope.

A modern solution to the issue would be to use Attributes if you need to access this data from other scopes/scripts, or replicate it from server to client lazily (be careful, Attributes don’t replicate the other way!). Roblox doesn’t give us anything else to easily modify Instances so far as to directly add properties, probably for security reasons, but Attributes work just fine for this kind of stuff.

I’m gonna take a stab and guess that you’re using a lot of inheritance in your code, which would make this a bit messier. Sadly, that’s about all you can do without utilizing _G, which I try not to do, especially in a case for storing large amounts of info like this. Chances are, though, I’ll come back to this in 15-16 hours and have something better for you, but this is all I got for now. Good luck with your project!

1 Like

Hi, it’s amazing to get you personally on board with the question after so long, awesome dude.

My project is actually quite new, so there’s not much inheritance (er… none at all, actually) but I’m planning to implement inheritance-aspects as things progress. For now, I’ve found a complete workaround; I iterate over all of the parts and have moved them all into a list of objects, and so, don’t need to use Part properties any more as long as I pass around the correct list items everywhere… which actually isn’t that bad, and is very clear. For anyone else who wants to copy:

{
   {
      Prop1 = "",
      Prop2 = "", -- etc
      Parts = nil  -- Assign this the part/model/etc
   },
   [ ... lots of these, added to a Table when iterating over the Parts that need properties]
}

But still… the entire Roblox world would be a better place if you could add custom properties to Parts that could refer to classes… and ObjectValues!

Thanks for the tip about the non-actionable .Parenting of the table: “Assigning a Parent “property” to your clTwr instance doesn’t do anything except create a dictionary index with the key “Parent””.

So, the Table now has a .Parent property (yay), but, Tables don’t implement any Parenting, so, the Parent has no idea about the Table. A shame! And I think that that answers my OP question, so thanks & I’ll assign Correct Answer & close up.

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