When 2 different scripts use a module, and that module has a variable, do the scripts share that variable?

Sorry if the title sounds confusing and all over the place, but I’m not 100% confident in my understanding of the way modules are ran and used with require(). For my question, I’ll use this example of a module I’m trying to make to be used across a large variety of weapons in my game.

local Weapon = {}

local WeaponUser

function Weapon:SetUser(player)
	WeaponUser = player
end


function Weapon:TagHumanoid(targetHumanoid)
	if not WeaponUser then
		warn("Weapon has no user, cannot tag humanoid.")
		return
	end
	local tag = targetHumanoid:FindFirstChild("LastHit")
	if tag then
		tag.Value = WeaponUser.Name
	else
		local newtag = Instance.new("StringValue")
		newtag.Name = "LastHit"
		newtag.Parent = targetHumanoid
		newtag.Value = WeaponUser.Name
	end
end

return Weapon

If Player1 joins the server, their weapon will require(WeaponModule), and run WeaponModule:SetUser(Player1). Then Player2 joins, and does the same thing but instead WeaponModule:SetUser(Player2). Would Player1 then have the problem of all their kills being tagged by Player2, or does the module give each player their own environment/copy of the functions and the variable WeaponUser at the start?

When requiring from the module, you are passing those functions to the tool script. This means each tools has a “copy” of the function, so each script will run them separately with the arguments gave to them.

You can easily confirm this using Roblox Studio test tools. Go to Test > Clients and Servers, select at least 2 players and press “Start”.

The person above already answered your question but i’ll show you a slight change to this to make it more aligned with how modules are typically used:

local Weapon = {}
Weapon.WeaponUser = nil

function Weapon:SetUser(player)
	self.WeaponUser = player
end

When you use : for a function instead of ., self is automatically passed as the first argument. “Self” is basically what the function is being called on, in this case, Weapon. So you can access WeaponUser through self.WeaponUser.


To help you better understand, this is also why the following code snippet works:

game.GetService(game, "RunService")
-- is the same as
game:GetService("RunService")
-- game is self

In the first one, you didn’t use the sugar syntax lua provides (:), so you had to pass self yourself. In this case, self was game.

TL;DR: there’s a difference between : and ., and since you’re using :, you should take advantage of it. Some modern code editors even warn you for using : and not using self.

1 Like

Thanks for the explanation, I was never really sure what the difference was between : and . until now

From experience when your module script returns a table and scripts edit the table (does not replicate to clients or back), if script A for example were to set a variable, script B will see this change as well (but only on the same machine).

Module script.

local mod = {}

mod.testvar = 1

return mod

Script A.

local module = require(workspace.ModuleScript)

module.testvar = 2

Script B.

local module = require(workspace.ModuleScript)

print(module.testvar) --Prints 2.

I tested this in studio, I can confirm that server scripts indeed do this.
Though, it does not replicate to clients, this is server - server only.

For 2 client scripts for the same client this applies as well, but it will not replicate to the server or other clients.

It’s like changing a NumberValue or StringValue object, the same machine and different scripts on that same machine can see it, but it will not replicate to others.

6 Likes

One question, did you test script A and script B on a client or server? and the machine you are referring to is only on the player’s device?

I forgot this thread existed.
I sorta figured the whole thing out after a while.

Module scripts are initiated by the first script that require()'s them and all variables returned by it (usually a single table) are shared, all scripts can see what’s inside the table even after it was modified.

Unless you’re using actors / multi-threading, module scripts can safely share variables between other scripts.

I understand, so I don’t need to replicate the values for each script that uses the script module

1 Like