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
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.
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.
local Players = game:GetService("Players")
local username = Players:GetNameFromUserIdAsync(userId)
local textLabel = script.Parent
textLabel.text = username
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.
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.
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)
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)
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)
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
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)
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:
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)
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.