XP Level up system not working

I have made a XP Level up system but in the Script I made it so When the player levels up the Required XP value is subtracted from there current XP value, so if they have more XP then what is Required they get the extra XP, but when subtracting it, the number changes to Minus there XP amount.
My Script:

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = plr
	local Cash = Instance.new("IntValue")
	Cash.Parent = leaderstats
	Cash.Name = "Cash"
	Cash.Value = 0
	local Rank = Instance.new("IntValue")
	Rank.Parent = leaderstats
	Rank.Name = "Rank"
	Rank.Value = 1
	local Exp = Instance.new("IntValue")
	Exp.Parent = plr
	Exp.Name = "Exp"
	Exp.Value = 0
	local RequiredExp = Instance.new("IntValue")
	RequiredExp.Parent = plr
	RequiredExp.Name = "RequiredExp"
	RequiredExp.Value = 50
plr.PlayerGui.MainGUI.StatsHUD.LevelHUD.Bar.Black.Clip:TweenSize(UDim2.new(plr.Exp.Value / plr.RequiredExp.Value, 0, 1, 0))
	Exp.Changed:Connect(function(Changed)
		if Exp.Value >= RequiredExp.Value then
			Exp.Value = Exp.Value - RequiredExp.Value -- Here is were I subtract the XP
			Rank.Value = Rank.Value +1
			RequiredExp.Value = RequiredExp.Value + 50
		end
	end)
end)
```

I am a bit confused on what is the problem here :sweat_smile: but i am assume you want it to continue subtract the Exp if they have Exp enough for Next Rank if that so just task.wait() should do the trick like this

Exp.Changed:Connect(function(Changed)
       task.wait()
		if Exp.Value >= RequiredExp.Value then
			Exp.Value = Exp.Value - RequiredExp.Value -- Here is were I subtract the XP
			Rank.Value = Rank.Value +1
			RequiredExp.Value = RequiredExp.Value + 50
		end
	end)

Like I said I don’t understand the problem what code I posted do is that it will give small delay and check if they have enough leftover EXP to rank up to another rank because without delay if player have large amount of EXP it will reached event limit (I have seen another OP post and this isn’t what OP looking for)

Hi!

I just forked (and changed it to fit into one script) the experience script from one of my projects, maybe you can use it.
It uses DataStore2 to save/load, but you can edit it to your liking.

local dataStore2 = require(game:GetService("ServerStorage"):WaitForChild("DataStore2"))

dataStore2.Combine(
	"MasterKey", 
	"Level",
	"Experience"
)

local RankData = {
	["RankCalculation"] = {
		-- Change these to your liking
		[1] = 600, -- Required base experience -- Plus current rank (will be added automatically in the ExperienceToLevelUp function)
		[2] = 1.25, -- multiplied by this (just makes it harder to level up for each level)
	};
	-- RankName is used for if you want a gui above their head to display
	-- a text. it could be anything from lvl1 being "Noob" to lvl50 being "Epic God"
	["RankName"] = { 
		[1] = "Rank 1",
		[2] = "Rank 2",
		[3] = "Rank 3",
		[4] = "Rank 4",
		[5] = "Rank 5",
		[6] = "Rank 6",
		[7] = "Rank 7",
		[8] = "Rank 8",
		[9] = "Rank 9",
		[10] = "Rank 10",
		[11] = "Rank 11",
		[12] = "Rank 12",
		[13] = "Rank 13",
		[14] = "Rank 14",
		[15] = "Rank 15",
		[16] = "Rank 16",
		[17] = "Rank 17",
		[18] = "Rank 18",
		[19] = "Rank 19",
		[20] = "Rank 20",
		[21] = "Rank 21",
		[22] = "Rank 22",
		[23] = "Rank 23",
		[24] = "Rank 24",
		[25] = "Rank 25",
		[26] = "Rank 26",
		[27] = "Rank 27",
		[28] = "Rank 28",
		[29] = "Rank 29",
		[30] = "Rank 30",
		[31] = "Rank 31",
		[32] = "Rank 32",
		[33] = "Rank 33",
		[34] = "Rank 34",
		[35] = "Rank 35",
		[36] = "Rank 36",
		[37] = "Rank 37",
		[38] = "Rank 38",
		[39] = "Rank 39",
		[40] = "Rank 40",
		[41] = "Rank 41",
		[42] = "Rank 42",
		[43] = "Rank 43",
		[44] = "Rank 44",
		[45] = "Rank 45",
		[46] = "Rank 46",
		[47] = "Rank 47",
		[48] = "Rank 48",
		[49] = "Rank 49",
		[50] = "Rank 50",
	};
}

-- experience-calculation for level-up function
local function ExperienceToLevelUp(level)
	local baseNumber = RankData["RankCalculation"][1]
	local multNumber = RankData["RankCalculation"][2]
	return math.round(baseNumber*(level*multNumber))
end


local defaultLevel = 1
local defaultExperience = 0

-- when players join function
game:GetService("Players").PlayerAdded:Connect(function(player)
	print("Started loading data...")
	-- create folder & instances for our DataStores. Used for replication to the client
	local FOL_PlayerData = Instance.new("Folder");FOL_PlayerData.Name = "PlayerData";FOL_PlayerData.Parent = player
	local INS_Level = Instance.new("IntValue");INS_Level.Name = "Level";INS_Level.Parent = FOL_PlayerData
	local INS_Experience = Instance.new("IntValue");INS_Experience.Name = "Experience";INS_Experience.Parent = FOL_PlayerData
	-- define our DataStores
	local DS_Level = dataStore2("Level",player)
	local DS_Experience = dataStore2("Experience",player)
	-- create functions for when our data in a DataStore updates
	local function updateLevel(value)
		print("local function 'updateLevel' ran...");INS_Level.Value = value
	end
	local function updateExperience(value)
		print("local function 'updateExperience' ran...");
		local CurrentLevel = DS_Level:Get()
		
		-- If CurrentLevel is above MaxLevel, then set the CurrentLevel to MaxLevel
		-- This is here because "updateExperience" will run more than once.
		-- Lets say they just earned 1005 exp
		-- but it takes 400 exp to level up to lvl 2
		-- and it takes 600 exp to level up to lvl 3
		-- then the ExperienceToLevelUp function will level them up to level 3 before
		-- updating the leftover experience they have (which in this case is 5 experience)
		-- So this below just makes sure that if they had experience enough to level
		-- from let's say 49 to 51, then it will set their level to 50, since
		-- this is our levelcap in this instance, and discard the rest of the experience, since they
		-- reached max level
		if CurrentLevel > #RankData["RankName"] then -- We take the amount of ranks in our table, and define that as our maxlevel
			CurrentLevel = #RankData["RankName"]
			value = 0
			DS_Level:Set(CurrentLevel)
			DS_Experience:Set(value)
		end
		if value >= ExperienceToLevelUp(CurrentLevel) then
			value -= ExperienceToLevelUp(CurrentLevel)
			CurrentLevel += 1
			if value == ExperienceToLevelUp(CurrentLevel) then
				value = 0
				CurrentLevel += 1
			end
			INS_Experience.Value = value
			DS_Level:Set(CurrentLevel)
			DS_Experience:Set(value)
		else
			INS_Experience.Value = value
		end
	end
	updateLevel(DS_Level:Get(defaultLevel))
	updateExperience(DS_Experience:Get(defaultExperience))
	print("Finished loading data...")
	-- call the functions automatically again, when a data updates
	DS_Level:OnUpdate(updateLevel)
	DS_Experience:OnUpdate(updateExperience)
end)