I don't understand how to get PlayerAdded to work in Studio

I am trying to test my game in studio, and am looking for leaderstats in my 1 local script, but it’s not being created. It has worked for a while, but I’m confused about what to do to fix this. This page says this, but I don’t understand how this would be different from a normal playeradded event.

  • This event does not work as expected in solo mode , because the player is created before scripts that connect to PlayerAdded run. To handle this case, as well as cases in which the script is added into the game after a player enters, create an OnPlayerAdded function that you can call to handle a player’s entrance.

If it’s not firing, there’s a good chance you’re creating the connection after you do something which causes the script to delay. Could you post your code?

2 Likes

That’s correct, but I have to to have the VIP Chat tags in my game. How do you suggest I fix this? The only way the chat tags will be loaded is if the connection for the chat tags starts before the character added, as otherwise, it checks after the player has already joined. (This is only the code I need to enter. Code before is all variables, and code after is unrelated.)

Code
--Chat Tags
ChatService.SpeakerAdded:Connect(function(playerName)
	local speaker = ChatService:GetSpeaker(playerName)
	local player = game.Players[playerName]
	print("Speaker added")

	if serverModule.ChatTags[player.UserId] then
		print("Found")
		speaker:SetExtraData("Tags",{serverModule.ChatTags[player.UserId]})

	end
end)

game.Players.PlayerAdded:Connect(function(player)
	--Make leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	local coins = Instance.new("NumberValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
	local playerInfo = Instance.new("Folder")
	playerInfo.Name = "PlayerInfo"
	playerInfo.Parent = player
	local obbyCompletions = Instance.new("NumberValue")
	obbyCompletions.Name = "ObbyCompletions"
	obbyCompletions.Parent = playerInfo
	local timePlayed = Instance.new("NumberValue")
	timePlayed.Name = "TimePlayed"
	timePlayed.Parent = playerInfo
	local robuxSpent = Instance.new("NumberValue")
	robuxSpent.Name = "RobuxSpent"
	robuxSpent.Parent = playerInfo
	local gamepassesOwned = Instance.new("Folder")
	gamepassesOwned.Name = "GamepassesOwned"
	gamepassesOwned.Parent = player

	gamepassesOwned.ChildAdded:Connect(function(child)
		serverModule.PassRewards(child.Name,player)
	end)

	--
	--for _, gamepass in pairs(serverModule.GamepassIds) do
	--	if MarketplaceService:UserOwnsGamePassAsync(player.UserId,gamepass.ID) == true then
	--		print("Owns Gamepass")
	--		local newGamepass = Instance.new("NumberValue")
	--		newGamepass.Value = gamepass.ID
	--		newGamepass.Name = gamepass.Name
	--		newGamepass.Parent = gamepassesOwned

	--		--Check to see if player should get VEP Chat tag
	--		print("About to loop")
	--		for _, gamepassInTable in pairs(serverModule.GamepassIds) do
	--			print("Looped")
	--			if gamepass.ID == gamepassInTable["ID"] and gamepassInTable["Name"] == "VEP" then
	--				print("Adding")
	--				--Add new chat tag for user
	--				local newTable = {}
	--				newTable.TagText = "VEP"
	--				newTable.TagColor = Color3.fromRGB(255,255,0)
	--				serverModule.ChatTags[player.UserId] = newTable
	--			end
	--		end
	--	end
	--end


	--Load player data
	local success, err = pcall(function()
		local playerData = playerDataStore:GetAsync(player.UserId)
		if playerData then
			coins.Value = playerData["Coins"]
			obbyCompletions.Value = playerData["Obby Completions"]
			timePlayed.Value = playerData["Time Played"]
			robuxSpent.Value = playerData["Robux Spent"]
		end
	end)

	--Make version ui display current game version
	local playerGui = player.PlayerGui
	local settingsGui = playerGui:WaitForChild("SettingsGui")
	local settingsFrameRounder = settingsGui:WaitForChild("SettingsFrameRounder")
	local settingsFrame = settingsFrameRounder:WaitForChild("SettingsFrame")
	local gameInformation = settingsFrame:WaitForChild("GameInformation")
	local serverVersion = gameInformation.ServerVersion
	local latestGameVersion = gameInformation.LatestGameVersion
	local gameVersion = gameInformationStore:GetAsync("Version")
	serverVersion.Text = "Game Version: " .. gameVersion
	latestGameVersion.Text = "Latest Version: " .. gameVersion
	local function checkForNewVersion()
		while true do
			local success, err = pcall(function()
				latestGameVersion.Text = "Latest Version: " .. gameInformationStore:GetAsync("Version")
			end)
			wait(30)
		end
	end
	spawn(checkForNewVersion)

	--Save data every 60 seconds and on game end


	local function autosave()
		while wait(60) do
			local data = {
				["Coins"] = coins.Value,
				["Obby Completions"] = player.PlayerInfo.ObbyCompletions.Value,
				["Time Played"] = player.PlayerInfo.TimePlayed.Value,
				["Robux Spent"] = player.PlayerInfo.RobuxSpent.Value
			}
			savePlayerData(player.UserId,data)
		end
	end
	spawn(autosave)


end)

Ah I see, I’ve ran into this issue before and I ended up having to create a coroutine that requires everything, then yielded the PlayerAdded function until chatService exists.

Something like this should work:

local chatService
coroutine.wrap(function()
    chatService = require(serverScriptService:WaitForChild('ChatServiceRunner'):WaitForChild('ChatService')
end)()

players.PlayerAdded:Connect(function(player)
    repeat wait() until chatService
    -- then the player should always "register" because we aren't delaying the thread by creating a coroutine
end)

You could also just iterate through the players

local function playerAdded(player)
    -- this would execute for every player
end
players.PlayerAdded:Connect(playerAdded)
for i,v in pairs(players:GetPlayers()) do
    playerAdded(v)
end
1 Like

I believe I did what you are saying here, and leaderstats still aren’t loading in.

I see what you mean, I’m guessing ChatService only loads in after a player joins, is that correct?

Script
--Editable variables
local NUMBER_OF_TYCOONS = 2

--Services
local Debris = game:GetService("Debris")
local DSS = game:GetService("DataStoreService")
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local ChatService

coroutine.wrap(function()
	ChatService = require(game.ServerScriptService:WaitForChild("ChatServiceRunner"):WaitForChild("ChatService"))
end)

--Other variables
local serverModule = require(script.ServerModule)

local gameInformationStore = DSS:GetDataStore("GameInformation")
local playerDataStore = DSS:GetDataStore("PlayerData")
local coinsDataStore = DSS:GetOrderedDataStore("CoinsLeaderboard")
local tycoonPlacement = game.Workspace:WaitForChild("TycoonPlacement")

local toggleTypingBubbleEvent = ReplicatedStorage:WaitForChild("ToggleTypingBubble")
local purchaseItemEvent = ReplicatedStorage:WaitForChild("PurchaseItemEvent")

local function savePlayerData(userId,data)
	playerDataStore:SetAsync(userId,data)
end

local coroSavePlayerData = coroutine.create(function(userId,data)
	playerDataStore:SetAsync(userId,data)
end)

--Spawning in all tycoons
for x = 1, NUMBER_OF_TYCOONS, 1 do
	local tycoonClone = game.ServerStorage:WaitForChild("TycoonToClone"):Clone()
	tycoonClone.Name = "Tycoon" .. x
	tycoonClone.Parent = game.Workspace.Tycoons
	local bridgeOrientation = tycoonPlacement["Tycoon" .. x].Orientation
	local bridgeRotFrame = CFrame.Angles(0,math.rad(bridgeOrientation.Y),0)
	tycoonClone:SetPrimaryPartCFrame(CFrame.new(tycoonPlacement["Tycoon" .. x].Position) * bridgeRotFrame)
end

--Chat Tags
ChatService.SpeakerAdded:Connect(function(playerName)
	local speaker = ChatService:GetSpeaker(playerName)
	local player = game.Players[playerName]
	print("Speaker added")

	if serverModule.ChatTags[player.UserId] then
		print("Found")
		speaker:SetExtraData("Tags",{serverModule.ChatTags[player.UserId]})

	end
end)

game.Players.PlayerAdded:Connect(function(player)
	repeat wait() until ChatService
	--Make leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	local coins = Instance.new("NumberValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
	local playerInfo = Instance.new("Folder")
	playerInfo.Name = "PlayerInfo"
	playerInfo.Parent = player
	local obbyCompletions = Instance.new("NumberValue")
	obbyCompletions.Name = "ObbyCompletions"
	obbyCompletions.Parent = playerInfo
	local timePlayed = Instance.new("NumberValue")
	timePlayed.Name = "TimePlayed"
	timePlayed.Parent = playerInfo
	local robuxSpent = Instance.new("NumberValue")
	robuxSpent.Name = "RobuxSpent"
	robuxSpent.Parent = playerInfo
	local gamepassesOwned = Instance.new("Folder")
	gamepassesOwned.Name = "GamepassesOwned"
	gamepassesOwned.Parent = player

	gamepassesOwned.ChildAdded:Connect(function(child)
		serverModule.PassRewards(child.Name,player)
	end)

	--
	--for _, gamepass in pairs(serverModule.GamepassIds) do
	--	if MarketplaceService:UserOwnsGamePassAsync(player.UserId,gamepass.ID) == true then
	--		print("Owns Gamepass")
	--		local newGamepass = Instance.new("NumberValue")
	--		newGamepass.Value = gamepass.ID
	--		newGamepass.Name = gamepass.Name
	--		newGamepass.Parent = gamepassesOwned

	--		--Check to see if player should get VEP Chat tag
	--		print("About to loop")
	--		for _, gamepassInTable in pairs(serverModule.GamepassIds) do
	--			print("Looped")
	--			if gamepass.ID == gamepassInTable["ID"] and gamepassInTable["Name"] == "VEP" then
	--				print("Adding")
	--				--Add new chat tag for user
	--				local newTable = {}
	--				newTable.TagText = "VEP"
	--				newTable.TagColor = Color3.fromRGB(255,255,0)
	--				serverModule.ChatTags[player.UserId] = newTable
	--			end
	--		end
	--	end
	--end


	--Load player data
	local success, err = pcall(function()
		local playerData = playerDataStore:GetAsync(player.UserId)
		if playerData then
			coins.Value = playerData["Coins"]
			obbyCompletions.Value = playerData["Obby Completions"]
			timePlayed.Value = playerData["Time Played"]
			robuxSpent.Value = playerData["Robux Spent"]
		end
	end)

	--Make version ui display current game version
	local playerGui = player.PlayerGui
	local settingsGui = playerGui:WaitForChild("SettingsGui")
	local settingsFrameRounder = settingsGui:WaitForChild("SettingsFrameRounder")
	local settingsFrame = settingsFrameRounder:WaitForChild("SettingsFrame")
	local gameInformation = settingsFrame:WaitForChild("GameInformation")
	local serverVersion = gameInformation.ServerVersion
	local latestGameVersion = gameInformation.LatestGameVersion
	local gameVersion = gameInformationStore:GetAsync("Version")
	serverVersion.Text = "Game Version: " .. gameVersion
	latestGameVersion.Text = "Latest Version: " .. gameVersion
	local function checkForNewVersion()
		while true do
			local success, err = pcall(function()
				latestGameVersion.Text = "Latest Version: " .. gameInformationStore:GetAsync("Version")
			end)
			wait(30)
		end
	end
	spawn(checkForNewVersion)

	--Save data every 60 seconds and on game end


	local function autosave()
		while wait(60) do
			local data = {
				["Coins"] = coins.Value,
				["Obby Completions"] = player.PlayerInfo.ObbyCompletions.Value,
				["Time Played"] = player.PlayerInfo.TimePlayed.Value,
				["Robux Spent"] = player.PlayerInfo.RobuxSpent.Value
			}
			savePlayerData(player.UserId,data)
		end
	end
	spawn(autosave)


end)

@7z99 I did what you said in deleted post. (or new post)

But wouldn’t this just cause unnecessary loops through players that have already had this happen?

You aren’t resuming the coroutine

coroutine.resume(coroutine.create(function()
    ChatService = require(whatever)
end)

But wrapping requires you to call it instead of resuming it which is why you need an extra pair of parentheses.

coroutine.wrap(function()
    ChatService = require(module)
end)()
1 Like

No, it should just iterate through the players who have joined before the connection was made

I tried this. It’s still based on a playeradded event after tags are added, so it does the same thing.

btw I’m going to be gone for a while, I’ll respond when I get back

1 Like

This is a shot in the dark but maybe the you could try using game:GetService instead of indexing the service? Not sure why it wouldn’t be working.

You mean for the serverscriptservice reference with the chat tags? That didn’t change anything.

Yeah and with the player service.