local Family = {}
Family.__index = Family
function Family.new(Name)
local self = {}
self.Name = Name
self.Age = 0
self.LifeExpectancy = math.random(60,90)
setmetatable(self, Family)
return self
end
function Family:AgeUp(Years)
self.Age += Years
print(self.Age)
if self.Age >= self.LifeExpectancy then
print("Is older than life expectancy")
-- fire event here
end
end
return Family
Then in a script:
local Family = require(game.ServerStorage:WaitForChild("Family"))
local Child = Family.new()
Child:AgeUp(100)
Child.Died:Connect(function()
print(Child.Name .. " has passed away.")
end)
I have tried using bindable events like this:
local Family = {}
Family.__index = Family
Family.Died = Instance.new("BindableEvent")
function Family:AgeUp(Years)
self.Age += Years
print(self.Age)
if self.Age >= self.LifeExpectancy then
print("Is older than life expectancy")
self.Died:Fire()
end
end
Child.Died.Event:Connect(function()
print(Child.Name .. " has passed away.")
end)
Maybe you should create the bindable event in the constructor? If you use the metatable’s event then the event will fire for every instance of the object, which might not be what you want.
He’s trying to use a bindable event to create a custom event for his object the same way a part has events like Changed, or Touched.
What I do is put a reference to the event in the object when it is instantiated, and an optional reference to the bindable’s actual event (to make it look more polished, that way you can do “object.SomeEvent:Connect” rather than “object.SomeEvent.Event:Connect”)
This code worked when I tested it:
local object = {}
object.__index = object
function object.new()
local newObject = {}
local event = Instance.new("BindableEvent")
newObject._EventRef = event -- only accessed internally, not needed by the user
newObject.SomeEvent = event.Event -- what the user binds their listeners to
return setmetatable(newObject, object)
end
function object:DoSomething(...)
self._EventRef:Fire(...)
end
local testObject = object.new()
testObject.SomeEvent:Connect(function(...)
print("Event was fired with args:", ...)
end)
testObject:DoSomething("a", "b", "c")
local Family = {}
Family.__index = Family
function Family.new(Name)
local self = {}
self.Name = Name
self.Age = 0
self.LifeExpectancy = math.random(60,90)
self.DiedEvent = Instance.new("BindableEvent")
self.Died = self.DiedEvent.Event
setmetatable(self, Family)
return self
end
function Family:AgeUp(Years)
self.Age += Years
print(self.Age)
if self.Age >= self.LifeExpectancy then
print("Is older than life expectancy")--It prints
self.DiedEvent:Fire()
end
end
Script:
local Child = Family.new()
Child:AgeUp(100)
Child.Died:Connect(function()
print(Child.Name .. " has passed away.")--Doesn't print
end)
This may not work depending on how you want the event to be used, but you could use a function call instead of an event when the member passes away, something like:
function Family:AgeUp(Years)
self.Age += Years
print(self.Age)
if self.Age >= self.LifeExpectancy then
print("Is older than life expectancy")--It prints
self:Died()
end
end
--Function called when the Family member passes away
function Family:Died()
print(self.Name .. " has passed away.")
end
This just seems like a safer object-oriented solution, because you’d be manipulating the object within one of its own functions, and better protecting its data.
If you need to know that the Family member has died outside of the object, you can still use a bindable event, but it would require a bit more reworking.
Try calling AgeUp after creating the connection and it should work. You’re calling AgeUp and then waiting for it to be called, which doesn’t make much sense.
there are modules for this, since BindableEvents do not associate with OOP
here’s a short one i typed up here, which might not work since i haven’t tested it yet
local SignalStatic = {};
SignalStatic.__index = SignalStatic;
local ConnectionStatic = {};
ConnectionStatic.__index = ConnectionStatic;
function SignalStatic.new(signalName: string): Signal
local signalObj: Signal = {
Name = signalName,
Connections = {},
YieldingThreads = {}
}
setmetatable(signalObj, SignalStatic);
return signalObj;
end
local function NewConnection(sig: Signal, func): Connection
local connectionObj: Connection = {
Signal = sig,
Function = func,
Index = -1
}
return setmetatable(connectionObj, ConnectionStatic);
end
local function threadFunc(func: any, args: GenericTable, handlerName: string)
local thread = coroutine.create(function()
func(unpack(args));
end)
local success, err = coroutine.resume(thread);
if not success then
error(err);
end
end
function SignalStatic:Connect(func): Connection
local connection = NewConnection(self, func);
connection.Index = #self.Connections + 1;
table.insert(self.Connections, connection.Index, conenction)
return connection;
end
function SignalStatic:Fire(...)
local args = table.pack(...);
local allCons = self.Connections;
local allThreads = self.YieldingThreads;
for index = 1, #allCons do
local connection = allCons[index];
if connection.Function ~= nil then
threadFunc(connection.Function, args, connection.Signal.Name);
end
end
for index = 1, #allThreads do
coroutine.resume(allThreads[index]);
end
end
function SignalStatic:Wait()
local args = {};
local thread = coroutine.running();
table.insert(self.YieldingThreads, #self.YieldingThreads + 1, thread);
args = { coroutine.yield() };
table.remove(self.YieldingThreads, #self. YieldingThreads);
return unpack(args);
end
function ConnectionStatic:Disconnect()
self.Function = nil;
self.Signal = nil;
self.Index = -1;
setmetatable(self, nil);
end