So this could be something going right over my head or my lack of experience with multi-script/modular systems and BindableFunctions:
So I have a basic OOP class setup (In a module) that a 'Main' script creates a "Fighter" object for a player that joins the server. This has methods in it that involve managing fighter attributes that have no problems at all. After a new object is created, it's placed into a table.
local FighterModule = require(ServerStorage.FighterModule) local fightersInServer = {} --stores fighter objects function onPlayerJoin(player) local NewFighter = FighterModule:Create(player) table.insert(fightersInServer, NewFighter) end game.Players.PlayerAdded:Connect(onPlayerJoin)
Now in my second server script, the purpose of it is to handle fighter abilities after the client calls for an ability. My issue then lies inside of the function that connects to my RemoteEvent. I wanted to use a BindableFunction to get the fighter from the table inside of my Main script, but it's giving out an error when I want to fire a method from my object.
Output Error: attempt to call method 'DoAbility' (a nil value)
What confuses me is that I can get a property from my fighter object like fighter.Name
but not one of the method, fighter:SomeMethod()
.
local requestFighterFunction = ServerStorage.BindableFunction function onAbility(player, arg1, arg2) --I have some args passed by the client local fighter = requestFighterFunction:Invoke(player) print(fighter.Name) --does print the name of the fighter fighter:DoAbility() --attempt to call method error end RemoteEvent.OnServerEvent:Connect(onAbility)
Now to finish off what I'm doing in my Main script is the listener to the BindableFunction which is supposed to return the fighter from the table of fighters:
local FighterModule = require(ServerStorage.FighterModule) local requestFighterFunction = ServerStorage.BindableFunction local fightersInServer = {} --stores fighter objects --This function is also used by this same script to save typing and works function getFighter(player) local found; for _, fighter in pairs(fighters) do if fighter.Name == player.Name then found = fighter end end return found end function onPlayerJoin(player) local NewFighter = FighterModule:Create(player) table.insert(fightersInServer, NewFighter) end game.Players.PlayerAdded:Connect(onPlayerJoin) requestFighterFunction.OnInvoke = getFighter
Not sure what I'm doing wrong or the fix to this. The other way to fixing it would be putting the entire scripts into one but I do want to keep them apart since they server different purposes.
Another thing I want to ask are better alternatives to what I'm doing if any. This is my first game project that I want to have a modular system for so the help is appreciated.
Let me know if I missed something you would like to know.
If I wasn't clear of what :DoAbility() is, it's a method in my class module that will do something. It's only a getter type of method right now.
ModuleScript:
local fighter = {} fighter.__index = fighter function fighter:Create(player) local self = setmetatable(fighter, {}) self.Name = player.Name --other stuff in here return self end --function in question. function fighter:DoAbility() --does stuff return self.SomeProperty end return fighter
Just typed this out right now and not in studio but should be a simpler version to my OOP class setup. Let me know if this is set up properly.
When you pass a table via a BindableFunction
, a copy of it is returned, not the actual table. Therefor it may not function properly if you applied metamethods to it, as the metatable is stripped from the copy of the table.
What you should do instead is either
a) Make it a function placed in a ModuleScript
rather than a BindableFunction
or
b) Pass the value via a global table, such as _G
or shared
(less recommended)