Singleton pattern question

Hi guys!

So I come from Unity and I’m very used to work with singleton managers in my games and I was wondering if this was possible in Luau.

Let’s say I have this script below, I feel like every time I would require this script somewhere to use it it would reassign my _instance variable, and then it wouldn’t really work right? Or am I not getting the gist of how metatables work? Thanks

-- Singleton.lua

local Singleton = {}
Singleton.__index = Singleton

local _instance

function Singleton.new()
   local self = setmetatable({}, Singleton)
   -- Initialize your private data here
   return self
end

function Singleton:getInstance()
   if _instance == nil then
       _instance = Singleton.new()
   end
   return _instance
end

return Singleton

From the things I read about singletons, I feel like a ModuleScript would somewhat achieve the same thing (ModuleScript | Documentation - Roblox Creator Hub)

I’m not really sure what you meant because, even though I’ve used Unity before, I somehow never heard of singletons before, although passing values through ModuleScript functions could work:

Main script inside your object or anywhere else:

local ServerScriptService = game:GetService("ServerScriptService")
local ModuleScriptName = require(ServerScriptService.ModuleScript) -- Or any other location in which you placed the module script
local Object = script.Parent -- Or any other object, doesn't have to be the script's parent

ModuleScriptName.MyFunction(Object) -- Send the object to the ModuleScript

ModuleScript:

local MyModule = {}

function MyModule.MyFunction(Object)
	Object.Color = Color3.new(0, 0.568627, 1) -- Make Object Blue
end

return MyModule

Hopefully I understood what you meant correctly and hopefully this helps!

2 Likes

Modulescripts only run once on the first require. Subsequent requires point to the original modulescript.

So in your code, the _instance variable should be the same across all requires if using the :Get instance metamethod you defined.

However, calling instance.new() would return a new object to the script making the call.

1 Like

When you require a ModuleScript, the result is cached, so when you require it later on, the same table will be returned (but the client and server get their own copy). What you decide to do is stylistic, but I generally don’t use metatables or the OOP idiom in a singleton and instead stick to using purely the dot operator instead.

-- Private data would be up here

local Service = {}

function Service.GetInstance()
	
end

-- Initializing code here, like hooking to a signal
-- This would only be run on the first require call

return Service
2 Likes

There’s also game frameworks that helps you with this structure such as knit (lua) or flamework (typescript) with roblox-ts

1 Like

Yeah… I already started and can’t be arsed to switch to Knit but I wanna learn it for sure it looks nice tbh!

1 Like

Thank you that answers the question I didn’t know that =)

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.