What approach should I have for lots of unqiue (but not) OOP objects?

Before I begin, I just want to say that I do not want to use inheritance. Grouping OOP objects and having them inherit from a shared or base class is not something I want to work with, not that it’s hard, but because I think it’s bad practice and unstable.

Anyways, I have a plot building project that I’m working on and there’s a lot of different objects you can build with. For example, there are the basic blocks like spheres, cylinders, wedges, and blocks but there’s also objects like fridges and beds.

All these objects have their own data that’s unique but they also have some shared data. An example is the fridge and cylinder object will have position and orientation data but only the fridge will have a method that allows it to be opened.

My question is how I should organize this type of structure without the use of inheritance? I’ve been looking into OOP factories(?) but I’m fairly new to OOP and I can’t see how that can be used in Studio?

Not only am I looking for the logic on an OOP factory that creates these objects but I need help with the explorer hierarchy organization as well. Should I have a constructor module for every object? If I don’t use inheritance, how can I organize them? What would that even look like?

Having built a plot based building system and working on it extensively over the years (for which I naively used OOP to think about the blocks as objects) and then reworking the same system but just using a simple procedural approach, I can tell you that it’s only going to get in the way and be an annoyance.

I don’t know why you think inheritance is bad practice, but Lua’s “implementation” of OOP is shaky to begin with, despite the fact that it’s really not needed here.

I think you’ll find that your project will become a lot more simplistic if you go ahead and approach it without the OOP mindset. Not to say OOP is a bad paradigm, but I just don’t see it benefitting you here. Besides, treating Instances as OOP objects is done by ROBLOX under the hood by default, so then creating a pseudo-object that points to an Instance is always going to be painful to work with.

Again, I speak from experience with this, having wrote the same system twice and working on both extensively with OOP and without, I can tell you the latter is much less of a headache to work with.

So how did I structure it? I just had a ReplicatedStorage folder that stored all of the blocks in their own subfolders as categories (e.g. bedroom kit, security kit), when I wanted to design the building mechanics I just handled it all inside a LocalScript, while placing common code in reusable ModuleScripts. It’s painless to extend and work with, works like a charm. Don’t overthink stuff like this, because when you do, it becomes painful to work with what you have created!

:^)

1 Like

I wanted to use OOP for the ease of having methods that are tailored to each object if necessary. For example calling :serialize() on a BasePart would be much different from calling it on a couch. The couch could have multiple color/material properties, the couch model can’t have a .Size but instead would have a Scale value, etc.

If you had a modern bedroom kit and one from medieval times, would you put them all under bedroom kit? Or should I create another subfolder under the bedroom kit for medieval and modern?

Would you be worried about exploiters ripping your games source? Or loading speeds being slower due to all the assets?

What’s an example of common code in this example?

(I don’t know how to do the quoted reply thing, so take each paragraph (or two) as an answer to each question).

I’m sure if it’s the difference between serializing single-part models and multi-part models, this does not need such generalization, but I can understand that perhaps you wish to serialize certain models in different ways depending on their context. In which case, you can easily do this by having different serialization methods in ModuleScripts which are called based on the type of model which is being handled.

For the second question, it’s up to you really. In my line of thought I’d probably separate the medieval and modern from each other. You can do deeper subfolders if that suits. e.g. in my game, I had House Interior Kit and Medieval Interior Kit. Up to you really!

Exploiters will always be able to steal your models. If the client has them loaded into memory, they’re up for grabs by the exploiters. There’s nothing you can really do about it, if it happens it happens, you can file a DMCA takedown on games that use stolen assets without your permission if it becomes problematic.

As far as loading speeds, I don’t know the intricacies with how the ReplicatedStorage container functions to answer this scientifically, I personally have not experienced any absurd memory consumption by having all of the parts located in this container, maybe ROBLOX just loads the instances stored in this container into memory on the fly or maybe it’s all loaded in at once. Either way, I don’t really know. I doubt it causes an issue, as I have not experienced any, (I have a few hundred blocks).

In terms of common code, I had common functions such as :WeldModel() (for welding model together, my building game has physics), I actually also had a module that would handle creating new blocks for the calling script to receive, stuff like :GetPlotFromPlayer() or :ClearPlot() (I have found that when you go to :ClearAllChildren() on a container that has a TON of blocks in it, a script timeout error can occur because it takes so long to delete so many parts in some cases, so I wrote a custom destruction algorithm, so having this function available in many different scripts is important). Not to mention all of the functionality for each block was located in a ModuleScript for convenience.

Overall, just keep it pretty simple, ModuleScripts and procedural programming should serve you very well in this endeavour.

Good luck!

2 Likes

To quote someones text, you just need to highlight thier text and this bar should pop up, “Quote”.

1 Like