RunService binds

I made a module to prevent re-using RunService connections for optimizations, this will use 1 single connection for every event firing all the connected functions you give them.

--!strict
local runService = game:GetService('RunService')

--> Binds
local Binds = {
	Heartbeat = {},
	RenderStepped = {},
	Stepped = {},
	PreRender = {},
	PreAnimation = {},
	PreSimulation = {},
	PostSimulation = {},
}

--> Class
local Class = {}

--> Private
local Connections = {
	Heartbeat = nil,
	RenderStepped = nil,
	Stepped = nil,
	PreRender = nil,
	PreAnimation = nil,
	PreSimulation = nil,
	PostSimulation = nil,
}

local function Update()
	for i, v in pairs(Binds) do
		if #v > 0 then
			if Connections[i] == nil then
				Connections[i] = runService[i]:Connect(function(dt)
					for i, v in pairs(Binds[i]) do
						task.spawn(v, dt)
					end
				end)
			end
		elseif #v == 0 then
			if Connections[i] ~= nil then
				Connections[i]:Disconnect()
				Connections[i] = nil
			end
		end
	end
end

--> Methods
function Class.Heartbeat(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.Heartbeat, callBack)
	Update()

	return function()
		local Index = table.find(Binds.Heartbeat, callBack)
		if Index == nil then return end

		table.remove(Binds.Heartbeat, Index)
		
		Update()
	end
end

function Class.RenderStepped(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.RenderStepped, callBack)
	Update()

	return function()
		local Index = table.find(Binds.RenderStepped, callBack)
		if Index == nil then return end

		table.remove(Binds.RenderStepped, Index)
		
		Update()
	end
end

function Class.Stepped(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.Stepped, callBack)
	Update()

	return function()
		local Index = table.find(Binds.Stepped, callBack)
		if Index == nil then return end

		table.remove(Binds.Stepped, Index)
		
		Update()
	end
end

function Class.PreRender(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.PreRender, callBack)
	Update()

	return function()
		local Index = table.find(Binds.PreRender, callBack)
		if Index == nil then return end

		table.remove(Binds.PreRender, Index)
		
		Update()
	end
end

function Class.PreAnimation(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.PreAnimation, callBack)
	Update()

	return function()
		local Index = table.find(Binds.PreAnimation, callBack)
		if Index == nil then return end

		table.remove(Binds.PreAnimation, Index)
		
		Update()
	end
end

function Class.PreSimulation(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.PreSimulation, callBack)
	Update()

	return function()
		local Index = table.find(Binds.PreSimulation, callBack)
		if Index == nil then return end

		table.remove(Binds.PreSimulation, Index)
		
		Update()
	end
end

function Class.PostSimulation(callBack : (deltaTime : number) -> ()) : () -> ()
	table.insert(Binds.PostSimulation, callBack)
	Update()

	return function()
		local Index = table.find(Binds.PostSimulation, callBack)
		if Index == nil then return end

		table.remove(Binds.PostSimulation, Index)
		
		Update()
	end
end

--> return
return Class

Usage:

local RunService = require(path-to-module)

local TestBind = RunService.Stepped(function(deltaTime : number)
    print('Stepped')
end)

task.wait(5)

TestBind() --> Will remove the function from the connection list
7 Likes

This looks usefull (very). I’ll probably gonna use it!

(I already found out lol) Ok so I found an error. I used RenderStepped and can’t use it again??? Is it supposed to be like this?

EDIT: Yup I forgot renderstepped can’t be used server side lol