Most efficient way to deal with userids and imagelabels

Hey, I am learning how to script in lua trying to transfer my skills from java to here, so it’ll be appreciated if this generous community can share some of their knowledge :slight_smile:

Anyways,

The image above is 10 different textlabels, the one in dark yellow is supposed to be the username, the one below is displaying whether the user has picked the character, while the unknown icon is supposed to be replaced with the thumbnail of the character they chose. This is a hardcoded gui with no functionality.

My question is what is the most efficient way to display usernames, with the character they chose in the imagelabels.

The way I imagine it would be, is storing the userids with the agent they chose, and pulling out that stored data and passing it through the imagelabel and textlabel.

– To also add
I am working with two teams, and I want each team to display their 5 teammates ids individually.

To get the player’s username from their userid you can use this API and display the results to a TextLabel.

But to answer your question, yes, storing their UserIds and the name of the agent they chose would be the most efficient. On roblox people can change their usernames, and saving their usernames can display old information. So it’s better to save their UserId because that’s tied with their account forever. (Unless Roblox re-assigns their id which doesn’t happen often). In-case you’re curious on why I said the save the agent’s name, it’s because you can’t save Instances or certain userdatas to a data store, so saving the name of the agent they chose and getting it afterwards would be the better option. For their character to show in the ImageLabels, you can tinker with ViewportFrames or create a pre-made image for them.


As for the teammate situation, you can create a for loop that scans for the players that’s on their team and requests for the server to give the client the proper information for it to display.

Sorry for the wall of text

1 Like

Appreciate the response, exactly what I needed.

However, how does data storing work on roblox? If possible could you direct me to some recourses I could use to help me on my journey.

Here’s a few API articles by Roblox:

So the issue I have with this is, that it repeats my userid for all 5 textlabels.

Alright, what’s the code you used? It might be a simple error.

I deleted it, but I am struggling on how to work with the userid api and text labels.

Since I’m on mobile now, I won’t be able to give code samples because of small the screen is but I can describe how it should work.

To use the GetNameFromUserIdAsync API is actually pretty simple. The first thing you want to do is get the Players service from the game using game:GetService("Players"). You Fran assign that to a variable for later use in the script. Once you set up the variable, use the Asynchronous method on the service:

local players = game:GetService("Players")
local username = players:GetNameFromUserIdAsync(userId)

The Async portion of the function lets you know that it’s making a web call and can possibly fail.

After setting this up, you can reference the TextLabel and set its text to the username variable.

I’m not the best at explanations

local Players = game:GetService("Players")
local username = Players:GetNameFromUserIdAsync(userId)
local textLabel = script.Parent

textLabel.text = username

perhaps something like this?

1 Like

Yes, exactly like that! But capitalize the “T” for

and replace “userId” with the actual player’s UserId.

If I’m correct I’m guessing you want to know how to use datastores?
If so I will try my best to explain how they work and give an example on creating one.

  1. First we want to reference the DataStore Service and creating a datastore by doing so:
local DataStoreService = game:GetService("DataStoreService")
local Datastore = DataStoreService:GetDataStore("PlayerData") --The parameter can be any string but lets say its the players data.
  1. Next we want to get the players data when they join the game so we will use PlayerAdded
    and run some code like so:
game.Players.PlayerAdded:Connect(function(Player) --PlayerAdded is a event within the Players service that returns the player instance when someone joins
	
end)
  1. We need to next request their data by calling GetAsync() within a Pcall to prevent erroring and dataloss.
game.Players.PlayerAdded:Connect(function(Player)
	local Success, Data = pcall(function() --Pcall to prevent errors
		return Datastore:GetAsync(Player.UserId) --Get data from the datastore
	end)
end)
  1. We can check if no errors happened and then continue to check if they have any previous data like so:
game.Players.PlayerAdded:Connect(function(Player)
	local Success, Data = pcall(function()
		return Datastore:GetAsync(Player.UserId)
	end)
	
	if Success then --Check if the request went right.
		if Data then
			--Player has previous saved data
		else
			--Player is new lets make them some data
		end
	else
		--Something went wrong.
	end
end)
  1. For this example we can use leaderstats to make a leaderboard in the top right of the screen by using a function with the parameters of the player and their data
local CreateLeaderstats = function(Player, Data)
	local Leaderstats = Instance.new("Folder") --Creates a new instance
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player --Parent the folder to the player
	local Coins = Instance.new("NumberValue")
	Coins.Name = "Coins"
	Coins.Value = Data.Coins --Set the coins in the leaderboard to their data
	Coins.Parent = Leaderstats
	--Lets do the same with level
	local Level = Instance.new("NumberValue")
	Level.Name = "Level"
	Level.Value = Data.Level
	Level.Parent = Leaderstats
end
  1. We also need to use the PlayerRemoving event (Opposite of PlayerJoining) to save their data when a player leaves the game.
game.Players.PlayerRemoving:Connect(function(Player)
	local Data = {
		["Coins"] = Player.leaderstats.Coins.Value, --Save their coins from the leaderboard
		["Level"] = Player.leaderstats.Level.Value --Save their level from the leaderboard
	}
	DataStore:SetAsync(Player.UserId, Data) --Save to their playerid and their data.
end)
  1. We can pass everything and put it all together:
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("PlayerData")

local CreateLeaderstats = function(Player, Data)
	local Leaderstats = Instance.new("Folder") --Creates a new instance
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player --Parent the folder to the player
	local Coins = Instance.new("NumberValue")
	Coins.Name = "Coins"
	Coins.Value = Data.Coins --Set the coins in the leaderboard to their data
	Coins.Parent = Leaderstats
	--Lets do the same with level
	local Level = Instance.new("NumberValue")
	Level.Name = "Level"
	Level.Value = Data.Level
	Level.Parent = Leaderstats
end

game.Players.PlayerAdded:Connect(function(Player)
	local Success, Data = pcall(function()
		return DataStore:GetAsync(Player.UserId)
	end)
	
	if Success then
		if Data then
			CreateLeaderstats(Player, Data) --They have previous data so we can just past it.
		else
			--Player is new lets make them some data
			local Data = {
				["Coins"] = 100, --Some default data for new players
				["Level"] = 1 --Some default data for new players
			}
			CreateLeaderstats(Player, Data) --Lets pass the player and their data
		end
	else
		
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	local Data = {
		["Coins"] = Player.leaderstats.Coins.Value, --Save their coins from the leaderboard
		["Level"] = Player.leaderstats.Level.Value --Save their level from the leaderboard
	}
	DataStore:SetAsync(Player.UserId, Data) --Save to their playerid and their data.
end)

If you want a video tutorial I have my own here:
Link to youtube

Also make sure you enable this setting to use datastores:

After all of this we have our system that saves the players data as well as using leaderstats
image

2 Likes

Argument 1 missing or nil - Client - Name:2

This is the error I get, I am not referencing the userID in line 2.

Yea, you have to replace “userId” with the actual player’s UserId. It can be accessed by their Player Instance in the Players service.

local userId = Player.UserId -- "Player" would be the player's instance for example if you were living through the players on a team

Also, @alphajpeg gave a great DataStore tutorial!

Brilliant, thank you for piecing together the information. This community is so great for new guys like me.

In real game practice, how do I avoid manually inputting their ids?

There’s multiple ways, but one way is looping through the Players:GetPlayers() function which returns all of the players in the game.

for _, player in pairs(Players:GetPlayers()) do
   local userId = player.UserId
   -- rest of the script
end

This goes through each player until the loop is broken or it ends.

You absolute legend <3

Been at this for hours, thank you so much.

But it repeats, which I believe is because I have the script repeating for each one.

Is there any workaround this?

To save you trouble in the future you mentioned that the system you want is somewhat like a party system with allowing users to invite their friends, etc to their party. Because of this I recommend looking into RemoteEvents which in simple terms allows the client to communicate with the server. If your wondering why I’m saying this is because I recommend that when someone creates a party it will create an array on the server and when that user clicks buttons locally such as a button to invite someone it will fire a remote event to the server to add that user to the array and then also fire back to the client to update the users images and so.

I’ll provide an example below:

--Server script

local ReplicatedStorage = game:GetService("ReplicatedStorage") --Get the service
local PartyRemote = ReplicatedStorage:WaitForChild("Party") --Wait for the party remote / instance to load
local Partys = {} --Create an array for the party


PartyRemote.OnServerEvent:Connect(function(Player, Event, RequestedUser) 
	--When the remote is fired it will always return the 
	--Player instance and then the parameters you want
	--like in our example it returns <Player> and then "RequestedUser"
	
	if Event == "CreateParty" then --Check if event equals "CreateParty"
		--I'd also make sure a previous party doesnt exist before they try to make a new one.
		local Party = {
			["Player1"] = Player.Name, --The player who fired the remote
			["Player2"] = "", --Not decided yet
			["Player3"] = "", --Not decided yet
			["Player4"] = "", --Not decided yet
			["Player5"] = "", --Not decided yet
		}
		Partys[Player.Name] = Party --Add the party with the creators name to the partys array
	elseif Event == "DeleteParty" then
		for i, Party in pairs(Partys) do
			if Party.Player1 == Player.Name then
				table.remove(Party, i) --Removes the party if the player name is the first player
			end
		end
	elseif Event == "InvitePlayer" then
		if game.Players:FindFirstChild(RequestedUser) then --If the requested user exists then
			--Add them to the party
		end
	end
end)

--Local script

local ReplicatedStorage = game:GetService("ReplicatedStorage") --Get the service
local PartyRemote = ReplicatedStorage:WaitForChild("Party") --Wait for the party remote / instance to load

CreatePartyButton.MouseButton1Click:Connect(function()
	PartyRemote:FireServer("CreateParty", "") --Fire the remote to create a party
end)

InvitePlayerButton.MouseButton1Click:Connect(function()
	PartyRemote:FireServer("CreateParty", "bxshh") --Fire the remote to invite bxshh to the party
end)

Directory for the remote, etc:
image

2 Likes

To avoid having multiple scripts for the same purpose, you can do the same thing that I did for the Players:GetPlayers() except with extra steps.

for _, v in pairs(script.Parent.Parent:GetChildren()) do
  if v:IsA("TextLabel") then
     -- the current object is a text label
     -- you can interact with it here
  end
end

For every iteration the loop does, you can have it assign the player’s UserId or Username to the text label. I would give a much simplified code sample but on mobile that would take forever to type.

Yeah, so what I’m doing is something like an attack and defend, two teams with the same character selection. Then the round starts. I just left this in my notes to look into.