Roblox Obby Percent UI buggy

I’ve seen this type of UI in most games i tried creating a simlar type of one but it keeps bugging also can yall give me feedback on how it looks and what to change it goes from around 29% back to 9% which is the correct percent do yall know the fix??
image
robloxapp-20241110-1303399.wmv (2.0 MB)

Client Side Script

local TweenService = game:GetService("TweenService")

local plrUI = game:GetService("Players").LocalPlayer.PlayerGui
local ScreenUI = plrUI:WaitForChild("CompletionBar")
local backgroundBar = ScreenUI.BackgroundFrame
local barFrame = backgroundBar.BarFrame
local percentText = backgroundBar.PercentText
local obbys = workspace:WaitForChild("Obbys"):GetChildren()

local player = game.Players.LocalPlayer
local totalObbys = #obbys
local debounce = false -- Debounce variable

-- Function to calculate color between red and green based on completion percentage
local function calculateColor(percentComplete)
	local red = 1 - (percentComplete / 100)
	local green = percentComplete / 100
	return Color3.new(red, green, 0)
end

-- Function to update the bar and percentage text
local function updateProgress(completedObbys)
	local percentComplete = math.clamp((completedObbys / totalObbys) * 100, 0, 100)
	percentText.Text = string.format("%.0f%%", percentComplete)

	-- Tween the progress bar width to the correct value based on completedObbys
	local goalSize = {Size = UDim2.new(math.clamp(completedObbys / totalObbys, 0, 1), 0, 1, 0)}
	local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
	local sizeTween = TweenService:Create(barFrame, tweenInfo, goalSize)
	sizeTween:Play()

	-- Tween the progress bar color
	local goalColor = {BackgroundColor3 = calculateColor(percentComplete)}
	local colorTween = TweenService:Create(barFrame, tweenInfo, goalColor)
	colorTween:Play()
end

-- Function to handle obby completion and update progress
local function onObbyCompleted()
	if debounce then return end -- Check debounce before proceeding
	debounce = true -- Set debounce to true to prevent re-entry

	-- Increment Checkpoint and update progress
	player.leaderstats.Checkpoint.Value = player.leaderstats.Checkpoint.Value + 1

	-- Reset debounce after a short delay
	task.delay(0.5, function()
		debounce = false
	end)
end

-- Listener for when the Checkpoint value changes, to update progress immediately
player.leaderstats.Checkpoint:GetPropertyChangedSignal("Value"):Connect(function()
	updateProgress(player.leaderstats.Checkpoint.Value)
end)

-- Connect each obby part to update progress when touched
for _, obby in pairs(obbys) do
	if obby:IsA("Part") and obby:GetAttribute("CheckpointNumber") then
		obby.Touched:Connect(function(hit)
			local character = hit.Parent
			if character and character:FindFirstChild("Humanoid") then
				local player = game.Players:GetPlayerFromCharacter(character)
				if player then
					if player.leaderstats.Checkpoint.Value < obby:GetAttribute("CheckpointNumber") then
						onObbyCompleted()
					end
				end
			end
		end)
	end
end

-- Initialize the player's progress on join
updateProgress(player.leaderstats.Checkpoint.Value)

Server Side Script

-- UI and Tweening References
local TweenService = game:GetService("TweenService")
local obbys = workspace:WaitForChild("Obbys"):GetChildren()

-- Function to get checkpoint part by number
local function getCheckpointPart(checkpointNumber)
	for _, checkpoint in pairs(workspace:GetChildren()) do
		if checkpoint:IsA("Part") and checkpoint:GetAttribute("CheckpointNumber") == checkpointNumber then
			return checkpoint
		end
	end
	return nil
end

-- Function to update progress bar and percentage display in player UI
local function updateProgressBar(player, completedObbys, totalObbys)
	local percentComplete = (completedObbys / totalObbys) * 100
	local playerGui = player.PlayerGui
	if playerGui then
		local screenUI = playerGui:WaitForChild("CompletionBar")
		local backgroundBar = screenUI:FindFirstChild("BackgroundFrame")
		local checkpointNumber = player.leaderstats.Checkpoint.Value -- Get the current checkpoint from leaderstats

		-- Assuming you have a separate TextLabel for the checkpoint number display:
		local checkpointText = screenUI:FindFirstChild("CheckpointText")

		if checkpointText then
			-- Update the TextLabel to show "Checkpoint: <checkpointNumber>"
			checkpointText.Text = "Checkpoint: " .. checkpointNumber
		end

		if backgroundBar then
			local barFrame = backgroundBar:FindFirstChild("BarFrame")
			local percentText = backgroundBar:FindFirstChild("PercentText")

			if barFrame and percentText then
				-- Update the percent text
				percentText.Text = string.format("%.0f%%", percentComplete)

				-- Tween the progress bar width
				local goal = {Size = UDim2.new(completedObbys / totalObbys, 0, 1, 0)}
				local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
				local tween = TweenService:Create(barFrame, tweenInfo, goal)
				tween:Play()
			end
		end
	end
end

-- Function to handle obby completion and update progress
local function onObbyCompleted(player, checkpointPart)
	local checkpointNumber = checkpointPart:GetAttribute("CheckpointNumber")
	local totalObbys = #obbys

	if player.leaderstats.Checkpoint.Value < checkpointNumber then
		-- Update completed obbys count and leaderstat
		player.leaderstats.Checkpoint.Value = checkpointNumber
		print("Player reached Checkpoint " .. checkpointNumber)

		-- Update progress bar
		updateProgressBar(player, checkpointNumber, totalObbys)
	end
end

-- Player join event
game.Players.PlayerAdded:Connect(function(player)
	-- Set up leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local checkpointStat = Instance.new("IntValue")
	checkpointStat.Name = "Checkpoint"
	checkpointStat.Value = 0
	checkpointStat.Parent = leaderstats
end)

-- Connect each obby part to update progress when touched
for _, checkpoint in pairs(obbys) do
	if checkpoint:IsA("Part") and checkpoint:GetAttribute("CheckpointNumber") then
		checkpoint.Touched:Connect(function(hit)
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			if player then
				onObbyCompleted(player, checkpoint)
			end
		end)
	end
end

please reply if you know anything!!

2 Likes

Their isn’t any need to use string.format?

1 Like

If I do this it has extra numbers and doesnt round

	percentText.Text = percentComplete
1 Like