Signals and Maid?

Hey guys i want to know what is Signals and Maids are and what can i use them for(Example could be great)

i have some code sample that i got:

local Maid = {}
Maid.__index = Maid

function Maid.new()
	local self = setmetatable({}, Maid)
	self.Tasks = {}
	return self
end

function Maid:Cleanup()
	for task, _ in pairs(self.Tasks) do
		task:Disconnect()
	end
	self.Tasks = {}
end

function Maid:GiveTask(task)
	self.Tasks[task] = true
end

function Maid:RemoveTask(task)
	self.Tasks[task] = nil
end

return Maid

local Signal = {}
Signal.__index = Signal

function Signal.new()
	local self = setmetatable({}, Signal)
	self.connections = {}
	return self
end

function Signal:Connect(callback)
	local connection = {
		callback = callback,
		Disconnect = function()
			self.connections[connections] = nil
		end
	}
	self.connections[connection] = true
	return connection
end

function Signal:Fire(...)
	for connection in pairs(self.connections) do
		connection.callback(...)
	end
end

return Signal
1 Like

I know there are some post about this but those are for other signals and Maid made by people i wanna how to use them in general

How to use a Maid class on Roblox to manage state | by James Onnen (Quenty) | Roblox Development | Medium This will teach you everything you need to know, read it all follow it step by step.

1 Like

If I can describe them shortly, here’s what they do:

  1. Maids are effective at managing RBXScriptConnections that often are causes of memory leaks in scripts, often due to connections not being disconnected in time or a reference still leading to the said connections.
  2. Signals are great for creating a kind of RBXScriptConnections without any instances, like “weightless” events. They help signal to other scripts via its functionality, often in the direction upwards. Or they’re really good at interjecting the moment of a certain code.

Let’s say you have a modulescript, for example: a MatchObject, which upon creation, creates 2 teams, creates a Ball from another object, lets call it BallObject, (which handles everything about the current ball in the match), and then starts the match.

Took it from my game, tried making it as clean and understandable as possible, i’m not the best at explaining things, but hopefully you’ll understand by the code. Let me know if you have any other questions.

local MatchObject = {}
local Maid = -- reference to maid
local BallObject = -- reference to the ballobject
local MatchSettings = -- reference to ur match settings

MatchObject.__index = MatchObject

local function createTeam(name, color: BrickColor) : Team
	local team = Instance.new("Team")
	team.Name = name
	team.TeamColor = color
	team.Parent = Teams
	team.AutoAssignable = false

	return team
end

local function removeTeams()
    for _,v in game.Teams:GetChildren() do
        if v.Name ~= "Players" then v:Destroy() end
    end
end

function MatchObject.new()
    local self = setmetatable({}, MatchObject)

    self._maid = Maid.new()
    self.Team1 = createTeam(MatchSettings.TEAM1_NAME, MatchSettings.TEAM1_COLOR)
    self.Team2 = createTeam(MatchSettings.TEAM2_NAME, MatchSettings.TEAM2_COLOR)

    -- call basic functions that handle the match
    self:_spawnBall()
    self:_startPosition()

    local function playerAdded(player)
        -- do something with player if he gets added while match is going
    end

    local function playerRemoved(player)
        local i1,i2 = #self.Team1:GetPlayers(), #self.Team2:GetPlayers()
        if i1 < 1 or i2 < 1 then
            self:Destroy()
        end
    end

    -- connect events and give them to maid so they can be cleaned up when game ends
    self._maid:GiveTask(self.Team1.PlayerAdded:Connect(playerAdded))
    self._maid:GiveTask(self.Team2.PlayerAdded:Connect(playerAdded))
    self._maid:GiveTask(self.Team1.PlayerRemoved:Connect(playerRemoved))
    self._maid:GiveTask(self.Team2.PlayerRemoved:Connect(playerRemoved))

    -- connect a function that will be called when the maid object is getting cleaned up
    self._maid:GiveTask(removeTeams)

    return MatchObject
end

function MatchObject:_startPosition()
    -- loop through every player, team them, teleport them, etc..
end

function MatchObject:onHitGoal(scoringTeam: string)
    -- do something when a goal is scored

    -- make a new ball
    self:_spawnBall()
end

function MatchObject:_spawnBall()
    if self._hooked then self._maid["__ball"] = nil end -- cleans up for BallObject, if a ball exists
    self._hooked = BallObject.new() -- Spawns a new ball
    self._maid["__ball"] = self._hooked

    self._hooked.OnHitGoal:Connect(function(scoringTeam: string)
        self:onHitGoal(scoringTeam)
    end)

    return self._hooked
end

function MatchObject:Destroy()
    -- game ended so clean up events
    self._maid:DoCleaning()
end

return MatchObject 

BallObject:

local BallObject = {}
local Maid = -- reference to maid
local Signal = -- reference to ur signal module

BallObject.__index = BallObject

function BallObject.new()
    local self = setmetatable({}, BallObject)

    self._maid = Maid.new()
    self.OnHitGoal = Signal.new()

    -- spawn a new ball and everything
    -- (don't forget to add it to maid, so it gets cleaned up.)

    self._maid:GiveTask(self.OnHitGoal)

    return BallObject
end

function BallObject:ballHitSomething(part: Part, scoringTeam: string)
    -- lets assume this function is called when the ball hits something.
    if part.Name == "Goal" then self.OnHitGoal:Fire(scoringTeam) end
end

function BallObject:Destroy()
    -- ball has been scored so clean up events, because MatchObject will spawn a new ball.
    self._maid:DoCleaning()
end

return BallObject

Do note that this is just one example, there are other stuff you could use them for, this is only my perspective of it.

Wow thank you guys so much! I now know how to use signals and maids