How to parent a custom OOP Class to the workspace?

Hello, it’s me! Today I searched a bit in the forum for interesting things and found a question that still remains unanswered:
Is it possible to get a custom property, that was created on a script, in another script?

So here, in this tutorial you will learn how to add/create your own properties to a part. I don’t find anything wrong with that, so when I look at the code. Only problem: you can only tell the object in the script itself, if you try to get it into another script, it won’t work. My real problem is this and it is very similar to what I showed about this:
Now let’s say I have a classe, and it’s called “Monster”:

local Monster = {}

function Module.new(Properties)
    local NewMonster = setmetatable({}, Monster)
    local Health, Attack, Model = unpack(Properties) --If we are saying that the Properties parameter is a table, we need this function
    NewMonster.Health = Health
    NewMonster.Attack = Attack
    NewMonster.Model = Model:Clone() --We need a model for our Monster
    NewMonster.Model.Parent = workspace
    return NewMonster
end

function Monster:attackPlayer(self, Player)
    --Do stuff
end

function Monster:Die(self)
    --Do stuff
end

return Monster

When i use this in a script:

--Script1
local MonsterModule = require(Module.path)
local Slime = Monster.new({100, 10, game.ServerStorage.MonsterModel})

We’re good so far, right? Only problem:

--Script2
local Monster = workspace.MonsterModel
print(Monster) --Prints the model
print(Monster.Health) --NIL

BOOM! We have 2 problems:

  1. We can‘t set the Class parent to the workspace as it not inherits from the Instance class
  2. And if it was possible, we will get nil.
    We just can‘t „instantice“ a custom classe, so we can only get this from the class in them we create this and no others classes.
    What I want to ask is that is there a solution to this problem (and I don’t want to use the variable _G)?

Thanks for reading:
~~Eterna

3 Likes

I don’t know, maybe you can use shared to share that variable across scripts. Or, you can attach a BindableEvent or Function(function preferred) to that specifec instance. So, everytime you make an object you would add an event as a child to that object.

So, instead of referencing the object:

local Monster = workspace.MonsterModel

You fire the function:

local Monster = workspace.MonsterModel.BindableFunction:Invoke() -- returns the data of the object
-- Rest of script

And then in the script that you made the object do something like:

local Slime = Monster.new({100, 10, game.ServerStorage.MonsterModel})
local Event = Slime.BindableEvent
Event.OnInvoke:Connect(function()
    return Slime
end)

You probably get the general just of it.

2 Likes

Yes, you could actually use that, but isn’t there really a simple method to parent a classe on the workspace? And for me the shared is the same as the _G variable, i not want this.

I’ve read about OOP and understood the concept of it, but I’ve never really seen the use of it so I never used it before.

This is the only method I know and thought of.

You can read more about metatables here.

I’ve read through the page and stumbled upon this:


__metatable


if present, locks the metatable so getmetatable will return this instead of the metatable and setmetatable will error. Non-function value.


1 Like

@VegetationBush BindableFunction is the only way to do this if you don’t track references of your object instances, but even then, you’d have to reference the tracker in the calling script to get the related obj

Could I ask why you’re not instancing an object for ‘Health’ though? You could keep a NumberValue inside of your ‘monster’ model, updated when changes are made, so that it’s easier for other scripts to access such menial info

1 Like

Yeah, I know this. That was just an example, but if I use a custom class (e.g. a new type of Vector3 or a class for vertices, and no, I don’t plan to do that), I’m using the example of the vertices now, you can’t just create a script that instantiates this thanks to the string values, e.g. a Suzanne Monkey of Blender has over 1000 vertices, so you’ll understand that I can’t create over 1000 string values. And I’m sure that string values have a limit, but it would be really nice if there was a way to get a custom property of a custom class here, so if we could overlay a class on top of the workspace. And I repeat this:
The slime is just an example, no, I’m not working on a monster, this is just to show the problem.

If it wasn’t clear, I’m sorry. I forgot to explain exactly that this is a ModuleScript, so OOP. And OOP actually works with metatables, here I used it:

And I just saw this thing today, but unfortunately I need an argumeter, and besides, if I create a slime with attack 100 and life 100, and I use this tip, what should I use? Well, it’s no use, because the variables are stored. And even if I play my own class, I still need an argumeter. And I need my own class, so do not create a new one. All this is unnecessarily complicated, simply because it doesn’t help me.

I know it’s super old, but I came across this post during research for a game I’m working on. For future readers, I think Roblox Attributes (released 2021) is a good solution to replicate this system.

For example, I create “custom” instances in my game like this:

function BuildingBlock.new(typeId, block)
    if RunService:IsServer() then
        if typeId ~= nil and block ~= nil then
            block.Name = GameStatModule.buildingBlocks[typeId]["Name"]
            block:SetAttribute("TypeId", typeId)
            block:SetAttribute("BlockPart", block)
            block:SetAttribute("SupportsMass", GameStatModule.buildingBlocks[typeId]["SupportsMass"])
        else
            warn("BuildingBlock:new() error. TypeId and BlockPart cannot be nil")
        end
    else
        warn("Client is attempting to create building block")
    end
end