Scripting a ground progress bar

Do i set the frame as the playerimage parent?

1 Like

You don’t need to set the parent anymore based on my comment above, but if you were to create ImageLabels for every player (since every player and the player count can change) then yes, you would set the parent to the frame. :slight_smile:

Script (from what you sent above) should be looking like this now:

local EndPosition = game.Workspace.End.CFrame.Position
local startPosition = game.Workspace.Arrow.CFrame.Position
local totalDist = (EndPosition	 - startPosition).Magnitude
local players = game.Players:GetPlayers()

-- Assuming all connected players are being calculated
for _,player in pairs(players) do
	local char = player.Character
	local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
	
	if humanoidRootPart then
		local dist = (EndPosition - humanoidRootPart.Position).Magnitude
		local playerImageContent, isReadyToBeUsed = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
		
		local playerImage = script.Parent.PlayerImage
		
		if isReadyToBeUsed then
			playerImage.Image = playerImageContent
		end
		
		local perc = 1 - (totalDist - dist)
		playerImage.Position = UDim2.fromScale(perc, 0)
	end
end
end)

EDIT: Should be taking advantage of that additional bool that :GetUserThumbnailAsync() returns to determine whether the playerImageContent has been retrieved successfully.

Tried this, no error but nothing works.
image
(nothing happens?)

Is this script in that LocalScript I see in the image you just sent? Or is it in another script?

Not even the playerImage loads, the image shows nothing

It is the script you have sent.

The best thing I can think of at this point is to get some prints in there and see where the code is getting to (because it’s running, it’s evident because the previous times, it’s been running).

local EndPosition = game.Workspace.End.CFrame.Position
local startPosition = game.Workspace.Arrow.CFrame.Position
local totalDist = (EndPosition	 - startPosition).Magnitude
local players = game.Players:GetPlayers()

-- Assuming all connected players are being calculated
print("Print 1")
for _,player in pairs(players) do
	local char = player.Character
	local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
	
	print("Print 2")
	if humanoidRootPart then
		print("Print 3")
		local dist = (EndPosition - humanoidRootPart.Position).Magnitude
		local playerImageContent, isReadyToBeUsed = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
		
		print("Print 4")
		local playerImage = script.Parent.PlayerImage
		print("Print 5")
		if isReadyToBeUsed then
			playerImage.Image = playerImageContent
		end
		print("Print 6")
		local perc = 1 - (totalDist - dist)
		playerImage.Position = UDim2.fromScale(perc, 0)
		
		print("Print 7")
	end
	
	print("Print 8")
end
end)

The character hasn’t loaded and the humanoidrootpart also hasn’t loaded so it doesn’t pass the if statement. We will use player.CharacterAdded:Wait() and char:WaitForChild("HumanoidRootPart", 2) with a timeout of 2 seconds.

local EndPosition = game.Workspace.End.CFrame.Position
local startPosition = game.Workspace.Arrow.CFrame.Position
local totalDist = (EndPosition - startPosition).Magnitude
local players = game.Players:GetPlayers()

-- Assuming all connected players are being calculated
for _,player in pairs(players) do
	local char = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = char:WaitForChild("HumanoidRootPart", 2)

	if humanoidRootPart then
		local dist = (EndPosition - humanoidRootPart.Position).Magnitude
		local content, isReady = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
		
		local playerImage = script.Parent.PlayerImage
		playerImage.Image = content
		
		local perc = 1 - (totalDist - dist)
		playerImage.Position = UDim2.fromScale(perc, 0)
	end
end
1 Like

What happened with the Render Stepped? It is needed to constantly update the position of the image labels. A for loop should be ran before the render stepped function that creates the image labels for each player using their username as the image label name to identify it in the render loop.

1 Like

Ah, I wondered what that bottom end) was for, let me update my solution:

local EndPosition = game.Workspace.End.CFrame.Position
local startPosition = game.Workspace.Arrow.CFrame.Position
local totalDist = (EndPosition	 - startPosition).Magnitude
local players = game.Players:GetPlayers()

-- Assuming all connected players are being calculated
game:GetService("RunService").RenderStepped:Connect(function()
	for _,player in pairs(players) do
		local char = player.Character
		local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
		
		if humanoidRootPart then
			local dist = (EndPosition - humanoidRootPart.Position).Magnitude
			local playerImageContent, isReadyToBeUsed = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
			
			local playerImage = script.Parent.PlayerImage

			if isReadyToBeUsed then
				playerImage.Image = playerImageContent
			end

			local perc = 1 - (totalDist - dist)
			playerImage.Position = UDim2.fromScale(perc, 0)
		end
	end
end)

https://gyazo.com/cfb1e0d91566f604cfcb0dcae7e5487a

There is no point getting the player image content in the render loop.
What should happen is before the loop starts, create a for loop that creates an image label for each player in the session.

2 Likes

Was just going to modify my script now. :slight_smile:

VERY SORRY, My script had an issue. Instead of:
local perc = 1 - (totalDist - dist)
use:
local perc = 1 - (dist / totalDist)

EDIT: I just quickly tested these values and they do work.

local EndPosition = game.Workspace.End.CFrame.Position
local startPosition = game.Workspace.Arrow.CFrame.Position
local totalDist = (EndPosition	 - startPosition).Magnitude
local players = game.Players:GetPlayers()

-- Lets loop through all of the players first and create the images for them.
for _, player in ipairs(players) do
	local playerImage = Instance.new("ImageLabel")
	playerImage.Name = player.Name .. "-Image" 
	playerImage.Parent = script.Parent

	local playerImageContent, isReadyToBeUsed = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
	if isReadyToBeUsed then
		playerImage.Image = playerImageContent
	end
end

-- Assuming all connected players are being calculated.
game:GetService("RunService").RenderStepped:Connect(function()
	for _,player in ipairs(players) do
		local char = player.Character
		local humanoidRootPart = char:FindFirstChild("HumanoidRootPart")
		
		if humanoidRootPart then
			local dist = (EndPosition - humanoidRootPart.Position).Magnitude
			local playerImage = script.Parent:FindFirstChild(player.Name .. "-Image")
			local perc = 1 - (dist / totalDist)
			playerImage.Position = UDim2.fromScale(perc, 0)
		end
	end
end)

This way, we’re not constantly requesting the Roblox API for the users thumbnail. This will also create the ImageLabels for every player.

EDIT: Considered the change from @MSYGamingTV, if this works, please give him the solution. :slight_smile:

1 Like

this works, but why is my avatar not on the frame?
image

Because the default ImageLabel uses pixels as size, and the Y position is never being defined, so you would have to mess around with the sizes and Y positions to your liking
Possibly by setting the size of the image label to UDim2.FromScale(something, 1)

Sorry, but how would i do this?

I have tried this, playerImage.Position = UDim2.fromScale(-1.408, 1)

but it doesnt work. Am i doing something wrong?