Nothing happens when I attempt to run a function from a ModuleScript

This problem is so niche that it’s difficult to come up with a good title.

Recently I wrote a module to simplify adding attributes to the player. However, despite whatever I do, no attributes are added to the player, and nothing is printed to output, I have no idea what is going wrong here, as I’ve done this before and had no issues. I’ve tried all I can and nothing has worked so far.

Module (PlayerAttributes):

local defaultStates = {
	["number"] = 10;
	["bool"] = true;
	["Color3"] = Color3.new(1,0,1);
}

local module = {}

function module.Create(player)
	local co = coroutine.create(function()
		for _,v in ipairs(defaultStates) do
			print(table.find(defaultStates,v),v)
			player:SetAttribute(table.find(defaultStates,v),v)
		end
		coroutine.yield()
	end)

	coroutine.resume(co)
end

function module.Append(player,attribute,value)
	player:SetAttribute(attribute,value)
end

return module

Server Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local PlayerAttributes = require(ReplicatedStorage.PlayerAttributes)

function playerAdded(player)
	PlayerAttributes.Create(player)
end

Players.PlayerAdded:Connect(playerAdded)

I would post what pops up in the output window, but as I previously stated, nothing happens at all.

What is the output? I want to know what is the output so that I can try helping.

Try using print to see how far the script runs

He said that nothing is printed on the output

Ok, He did not added any print in the script.

It might not be a problem with a module script looking at this quick glance of code but instead a problem with PlayerAdded for when the player joins before this connection is able to run. Make sure to consider this gotcha condition as explained by Sleitnick.

    for _,player in pairs(game:GetService("Players"):GetPlayers()) do
        spawn(function()playerAdded(player)end)
    end
1 Like

I tried this:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local PlayerAttributes = require(ReplicatedStorage.PlayerAttributes)

function playerAdded(player)
	PlayerAttributes.Create(player)
end

for _,player in pairs(Players:GetPlayers()) do
	spawn(function()playerAdded(player)end)
end

and…

Nope, still nothing in output.
image

Nor is there anything under attributes on the player.
image

Note: I switched between both client and server and the output and attribute panel are still blank.

Just noticed I did it wrong,
Meant to do this:

Players.PlayerAdded:Connect(playerAdded)

for _,player in pairs(Players:GetPlayers()) do
	spawn(function()playerAdded(player)end)
end

However still nothing has changed, at this point I’m considering dropping this idea and using CollectionService instead.

Weren’t you supposed to do this if you watched the video both the connection and the loop to cover players who already joined the game?

function playerAdded(player)
	PlayerAttributes.Create(player)
end

Players.PlayerAdded:Connect(playerAdded)--for new players after script connection runs

for _,player in pairs(Players:GetPlayers()) do -- for players who already joined
	spawn(function()playerAdded(player)end)
end

I know, I corrected my mistake in post #7

iirc, table.find finds the position of a given value if the table is an array, but the defaultStates is a dictionary this means that

will print: nil v

After extensive print debugging I have found the issue.

you gotta use pairs for dictionaries. I pairs goes through numeric indexes which a dictionary doesn’t have and hence won’t run at all. Never knew this pretty interesting, I never use ipairs as much as pairs I usually use numeric loops :stuck_out_tongue: as a habit.

function module.Create(player)
	print("Yo im module")
	local co = coroutine.create(function()
		print("Coroutine is running")
		for i,v in pairs(defaultStates) do
			print(i,v)
			player:SetAttribute(i,v)
		end
	end)
	coroutine.resume(co)
end

Edit: Also no need to yield it, I believe Roblox already handles it for you through the “magic” that is garbage collection.

2 Likes

yes, and also the changes you made inside the for loop will work, since printing i means printing the key name and printing v, will print the value of the key name. The same goes for player:SetAttribute

2 Likes

I never knew this, I always thought that ipairs was better than pairs, but never knew why.

This is very useful, I almost never use the first variable in “for i,v” loops and didn’t consider that this may be the solution.

Thanks, both of you, this really helps a lot!

2 Likes

when looping through an array, all the values are indexed by a number, so use for i, v in pairs when looping the table. i = index or position, and v = value
when looping through a dictionary, all the values are indexed by a key name, so use for k, v in pairs.
k = keyname, and v = value
This is not necessary but a good practice

1 Like