Table nil outside of playeradded event?

So I have tried to print debug and it printed the table in this section of my script:

PlayerData[player] = localdata
print(PlayerData[player]) --prints

But when I try to do this

game.ReplicatedStorage.Data.OnServerInvoke = function(player)
    local data = PlayerData[player]
    print(data) --prints nil
    if not data then return end
    return data.Data
end

Note: PlayerData start variable is not inside of the playeradded

Not sure what the error is because i’ve tried many things to fix this.

What is the type of “player” in the first example and what is “player” in the second one?
Edit: Upon rereading, If the second example has Player as an instance, instances cannot be keys, they can be values though, which might be why you’re getting nil. Also where is example 1? Is it in a separate script, local script or script?

ill send you the full event part they are all in the same script btw

game.Players.PlayerAdded:Connect(function(player)
	local localdata = {}
    local success,wins = pcall(WinsDataStore.GetAsync,WinsDataStore,player.UserId)
	local success2,credits = pcall(WinsDataStore.GetAsync,WinsDataStore,player.UserId)
    if not wins then
        localdata.UpdatedWins = true
    end
	if not credits then
        localdata.UpdatedCredits = true
    end
    localdata.Wins = wins or 0
 	localdata.Credits = credits or 0
    if not success then
        localdata.Wins = 0
        localdata.Error = true
        RemoteEvents.DataLoadFail:FireClient(player,"Wins failed to load")
    end
	if not success2 then
        localdata.Credits = 0
        localdata.Error = true
        RemoteEvents.DataLoadFail:FireClient(player,"Credits failed to load")
    end
    local leaderstats = Instance.new"Folder"
    leaderstats.Name = "Hidden"
    local WinsObject = Instance.new"IntValue"
    WinsObject.Value = localdata.Wins
    WinsObject.Name = "Wins"
    WinsObject.Parent = leaderstats
	local WinsObject = Instance.new"IntValue"
    WinsObject.Value = localdata.Credits
    WinsObject.Name = "Credits"
    WinsObject.Parent = leaderstats
    leaderstats.Parent = player
    local success2,data = pcall(MainDataStore.GetAsync,MainDataStore,player.UserId)
    if success2 then
        if not data then
            localdata.Updated = true
        end
        data = data or {
            -- index 1 is owned towers
            {{1}},
            -- index 2 is equipped towers
            {1}
        }
        local back = 0
        local owned,equipped = data[1],data[2]
        for i=1,#owned do
            if not GetTowerById(owned[i-back][1]) then
                table.remove(owned,i-back)
                back = back + 1
                localdata.Updated = true
            end
        end
        back = 0
        for i=1,#equipped do
            if not GetTowerById(equipped[i-back]) then
                table.remove(equipped,i-back)
                back = back + 1
                localdata.Updated = true
            end
        end
        localdata.Data = data
    else
        localdata.Error = true
        RemoteEvents.DataLoadFail:FireClient(player,"Data failed to load")
    end
    PlayerData[player] = localdata
end)
game.ReplicatedStorage.Data.OnServerInvoke = function(player)
    local data = PlayerData[player]
    if not data then return end
    return data.Data
end

Ah hold on a second I made a mistake, you can have instances as keys, my bad. Is PlayerData a global? Edit: Thought of something, try printing player.

its defined at the top of the script like this

local PlayerData = {}

Btw I mean print player in

Because the issue may not be in this script but in whatever script calls that RemoteFunction

I have this in a localscript

local data = game.ReplicatedStorage.Data:InvokeServer()

Yes but are you invoking an actual player when you use

Data:InvokeServer()

For instance are you doing:

local Player = game.Players.Whoever123
Data:InvokeServer(Player)

or are you sending something different, Like their name?

the datastore uses the player object itself.

Send us the code for whenever you invoke the server

You don’t need to do that, the player parameter is added automaticly

Yes but you’re invoking the data remote function on the client, so can you send us the client code?

local data = game.ReplicatedStorage.Data:InvokeServer()

this in better explanation is supposed to get the data so you can equip towers and stuff

local data = game.ReplicatedStorage.Data:InvokeServer()
function equipcheck(id)
        for i,v in ipairs(data[2]) do
            if v == id then
                return i
            end
        end
    return false
end
local ids = require(game.ReplicatedStorage.Modules.Data.id)
for k,o in pairs(require(game.ReplicatedStorage.Modules.Data)) do
				print(o.Id)
				if o.Id and equipcheck(o.Id) then
					print(o.Name)
					--hi.Parent.towers[data[1][tonumber(v.Name)][1]] = o.Name
				end
			end
``` I was using this to test.

Oh right, the player invoking is automatically added as the first argument.

Perhaps add a check to make sure the data is there first before returning

like

repeat wait() until PlayerData[Player]

I realize you already have a check, But it is placed under the code that’s erroring, So maybe put it above.

So let me summarize, It prints nil when its invoked but not when I print it inside the playeradded event that would most likely just run forever. Edit: Doesn’t error it just prints nil

Probably because you’re invoking it before the data is added. So add a repeat wait check.

1 Like

Thanks it worked I hope you have a good day!

1 Like

I would like to also add: The reason it was not loaded is because you have loops inside the player added event. which causes the code to pause.

You can use the following to run loops without hindering code speed:

coroutine.wrap(function()
	for i = 1,5 do
		print(i)
	end
end)()

spawn(function()
	for i = 1,5 do
		print(i)
	end
end)

Noted. I hope that I can use that in the future.