Getting data from an OOP Object w/o making a new object?

Sorry if anything is badly explained or if I used the wrong terms. I’m not experienced in this style of programming so I’m trying to ease into it with this!

Pretty much, I’m wondering how I can fetch data from a pre-existing OOP Object (from another script), without creating a new Object completely ruining the system + game.

Here’s some placeholder code, and afterwards I’ll tell you about my issues with it.

local Module = {}

function Module.new(player)
    local self = setmetatable({}, {__index = Module})

    self.PlayerData = {}
    return self
end)

return Module

So, if I went to a script and did the following;

local PlayerData = require(script.PlayerData)

game.Players.PlayerAdded:Connect(function(plr)
    local  Data = PlayerData.new(plr)
    data.Coins = 10
end)

…it’d work. I can change it as much as I’d like within that function, however if I wanted to retrieve the above PlayerData from another script, I couldn’t. Anytime I’d do local Data = PlayerData.new(plr) in a new script it’d just make a duplicate which I do not want. I’ve tried making a get function, but I haven’t figured out how to get self from it because simply going;

local Module = {}

function Module:Get()
    return self.PlayerData
end)

function Module.new(player)
    local self = setmetatable({}, {__index = Module})

    self.PlayerData = {}
    return self
end)

return Module

…doesn’t return because It just doesn’t work AFAIK. I’ve tried making an “AllPlayerData” table in the script, and while it technically works, it doesn’t update when I do data.Coins = 10, which is the entire reason for me structuring it this way. Thanks for anyone who can help!

I recommend using folders on players objects, because modules are hard to use if you arent familiar with the modules.

If you need an explanation why this doesnt work, ask me.

1 Like

I would, typically, however if I don’t learn it now when am I? This is just a small little thing for me to do to try and familiarize myself with different styles and methods to achieve (hopefully) greater feats. So whilst I know of other methods that will 100% work and would (otherwise) use, I’m looking to learn this way just to expand on my knowledge! :slight_smile:

According to my experience with the modules, works like this:

local module = require(module) ← here you are reciving a copy of the module, so if you do the same in another script, it will give another copy of the module.
How to fix this problem, is easy, use only one script and then connect different modules.

I hope this helps you understand the modules.

3 Likes

Usually I use another module and call it instanceToObject.

Then just use it as a dictionary

InstanceToObject[player object] = object.new()

You could use _G as well but it’s not recommended.

To handle clean up use .Ancestry changed to detect if the parent is nil and set the dictionary key value pair to nil.

The .Destroying event is still WIP I believe.

1 Like

Seems quite feasible! I’ll definitely add this to my list of options whenever I wake up! Only concern is it sounds a little hacky but maybe I’m imagining things. I’ll evaluate what I should do in the morning and let ya know how it works if I choose it. Thanks! :slight_smile:

1 Like

No problem.

Either way to share script data the only options available are module scripts and _G usually in table form.

You could also look into frameworks which often does the job of script to script communication which does something similar but make it more formal like Knit framework which standardizes it with getter functions like Knit.getService().

Maybe make your own, usually better for your personal understanding and to tailor fit it and trim the needed functions and unneeded ones.

1 Like

If you want something like this to work then I’d suggest only using the :Get method in other scripts. There needs to be some modifications to it as well:

local Players = game:GetService("Players")

local cache = {}

-- Clean up the cache to avoid memory leak
local function onPlayerRemoving(player)
    cache[player] = nil
end
Players.PlayerRemoving:Connect(onPlayerRemoving)

local Module = {}

function Module.get(player)
    if not cache[player] then
        cache[player] = Module.new(player)
    end
    assert(cache[player] ~= nil) -- Optional assert statement but the code assumes cache[player] ~= nil
    return cache[player]
end)

function Module.new(player)
    local self = setmetatable({}, {__index = Module})

    self.PlayerData = {}
    return self
end)

return Module
1 Like

I don’t think this is actually true. From the docs: “ModuleScripts run once and only once per Lua environment and return the exact same value for subsequent calls to require” which means that there is one version for the client and one version for the server.

This is equivalent to saying each Script gets the same thing from require, and each LocalScript gets the same thing from require. The LocalScript and Script versions are different though.

1 Like

“ModuleScripts run once and only once per Lua environment and return the exact same value for subsequent calls to require”
Each script/localscript is a lua environment, thats why isnt working the script.

1 Like

Every script shares the same server lua environment. Each localscript shares the same client lua environment. I can share a place file to prove this. How do you think _G works across scripts if they don’t share the same environment?

Here is a place file showing two scripts getting the same value from one module.

ModuleDemo.rbxl (36.2 KB)

How do you think _G works across scripts if they don’t share the same environment?
You are right about _G, but modules scripts are not shared between scripts and local scripts.

I take it you haven’t tried the place file I sent then?

Alredy tried and doesnt work like you think it would or at least in my computer.