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.
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
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.
Nor is there anything under attributes on the player.
Note: I switched between both client and server and the output and attribute panel are still blank.
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
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 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.
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
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