Data not saving

Hello, im making level system and i stuck with a problem that it just dont saving, im using profile store, and i really dont understand why some data are saving but level data is not saving: Code

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Server = game:GetService("ServerScriptService")

local ServerStorage = game:GetService("ServerStorage")
local ProfileStats = require(ServerStorage.Modules.ModuleScripts.Data.PlayerStats)

local DEFAULT_DATA = require(script.Player)
local ProfileStore = require(Server.Modules.ProfileStore.ProfileStore)

local DATA_STORE_KEY = "PLAYER_DATA"
if RunService:IsStudio()  then
	DATA_STORE_KEY = "PLAYER_STUDIO_TEST"
end

local PlayerStore = ProfileStore.New(DATA_STORE_KEY, DEFAULT_DATA.DEFAULT_PROFILE)
local Profiles: {[player]: typeof(PlayerStore:StartSessionAsync())} = {}

local Local = {}
local Shared = {}

function Local.OnSpawn()
	for _, player in Players:GetPlayers() do
		task.spawn(Local.LoadProfile, player)
	end
	
	Players.PlayerAdded:Connect(Local.LoadProfile)
	Players.PlayerRemoving:Connect(Local.RemoveProfile)
end

function Local.LoadProfile(player : Player)
	local profile = PlayerStore:StartSessionAsync(`{player.UserId}`, {
		Cancel = function()
			return player.Parent ~= Players
		end,
	})
	
	if profile == nil then
		return player:Kick("ProfileStore Error 1: No data profile found. Try rejoining the game")
	end
	
	profile:AddUserId(player.UserId)
	profile:Reconcile()
	
	profile.OnSessionEnd:Connect(function()
		Profiles[player] = nil
		player:Kick("Profile seasion ended. Try rejoining")
	end)
	
	local inGame = player.Parent == Players
	if inGame then
		Profiles[player] = profile
		
		
		ProfileStats.New(player)
		ProfileStats.SetStats(player, profile.Data.Level, profile.Data.Exp)
		
		while true do
			wait(1)
			print(player.STATS.Level.Value)
		end
	else
		profile:EndSession()
	end
end

function Local.RemoveProfile(player : Player)
	local profile = Profiles[player]
	if profile ~= nil then
		profile:EndSession()
	end
end

function Shared.GetData(player : Player): DEFAULT_DATA.PlayerData?
	local profile = Profiles[player]
	if not profile then return end
	
	return profile.Data
end


Local.OnSpawn()

return Shared
local PlayerStats = {}

local replicatedModules = game.ReplicatedStorage.Modules:WaitForChild("ModuleScripts")
local CalculateStats = require(replicatedModules:WaitForChild("CalculateStats"))

local remoteEvents = game.ReplicatedStorage.Remotes:WaitForChild("RemoteEvents")
local levelUpRE = remoteEvents:WaitForChild("OnLevelUp")


function PlayerStats.New(plr: Player)
	local statsFolder = Instance.new("Folder")
	statsFolder.Name = "STATS"
	statsFolder.Parent = plr

	local levelValue = Instance.new("IntValue")
	levelValue.Name = "Level"
	levelValue.Parent = statsFolder

	local expValue = Instance.new("IntValue")
	expValue.Name = "Exp"
	expValue.Parent = statsFolder
end

function PlayerStats.AddExp(plr: Player, expToAdd: number)

	local plrStats = plr:FindFirstChild("STATS")
	if not plrStats then
		warn(plr.Name .. " has no STATS folder! (AddExp)")
		return
	end

	local plrLVL = plrStats:FindFirstChild("Level")
	local plrEXP = plrStats:FindFirstChild("Exp")
	if not plrLVL or not plrEXP then
		warn(plr.Name .. " is missing Level or Exp Value! (AddExp)")
		return
	end

	local currentLevel = plrLVL.Value
	local newExp = plrEXP.Value + expToAdd

	PlayerStats.SetStats(plr, nil, newExp)

	local newLevel = plrLVL.Value

	if newLevel > currentLevel then
		levelUpRE:FireClient(plr)
	end
end

function PlayerStats.SetStats(plr: Player, newLevel: number?, newExperience: number?)

	local plrStats = plr:FindFirstChild("STATS")
	if not plrStats then
		warn(plr.Name .. " has no STATS folder! (SetStats)")
		return
	end

	local plrLVL = plrStats:FindFirstChild("Level")
	local plrEXP = plrStats:FindFirstChild("Exp")
	if not plrLVL or not plrEXP then
		warn(plr.Name .. " is missing Level or Exp Value! (SetStats)")
		return
	end

	if not newLevel and not newExperience then
		return
	end

	if not newLevel then
		newLevel = CalculateStats.FromExp(newExperience)
	end
	if not newExperience then
		newExperience = CalculateStats.FromLevel(newLevel)
	end

	plrLVL.Value = newLevel
	plrEXP.Value = newExperience
end

return PlayerStats
2 Likes

I may be blind as its still early but where are you adjusting the level value? Or do you just calculate it everytime the player joins?

I have module script which basically calculates level and exp, but im adjusting it in gui(local script), there is code: (sorry if i not understanded it right)

local barGui = script.Parent:WaitForChild("LevelBarGui")
local barBG = barGui:WaitForChild("BarBackground")
local barContainer = barBG:WaitForChild("BarContainer")
local barClipping = barContainer:WaitForChild("Clipping"); barClipping.AnchorPoint = Vector2.new(0, 0.5); barClipping.Position = UDim2.new(0, 0, 0.5, 0)
local barBar = barClipping:WaitForChild("Bar"); barBar.AnchorPoint = Vector2.new(0, 0.5); barBar.Position = UDim2.new(0, 0, 0.5, 0)
local currentLevelText = barBG:WaitForChild("CurrentLevel")
local nextLevelText = barBG:WaitForChild("NextLevel")
local expText = barBG:WaitForChild("Exp")

local levelUpGui = script.Parent:WaitForChild("LevelUpGui"); levelUpGui.Enabled = false
local levelUpBG = levelUpGui:WaitForChild("Background")
local levelUpTitle = levelUpBG:WaitForChild("Title")
local levelUpText = levelUpBG:WaitForChild("Body")

local plr = game.Players.LocalPlayer
local plrStats = plr:WaitForChild("STATS")
local plrLVL = plrStats.Level
local plrEXP = plrStats.Exp

local replicatedModules = game.ReplicatedStorage.Modules:WaitForChild("ModuleScripts")
local CalculateStats = require(replicatedModules:WaitForChild("CalculateStats"))

local remoteEvents = game.ReplicatedStorage.Remotes:WaitForChild("RemoteEvents")
local levelUpRE = remoteEvents:WaitForChild("OnLevelUp")

local tweenService = game:GetService("TweenService")

local prefix = "Lv. "


barClipping:GetPropertyChangedSignal("Size"):Connect(function()
	barBar.Size = UDim2.new(1/barClipping.Size.X.Scale, 0, 1, 0)
end)

function OnExpChanged()
	
	local previousExp = CalculateStats.FromLevel(plrLVL.Value)
	local nextExp = CalculateStats.FromLevel(plrLVL.Value + 1)
	
	local currentExpTotal = plrEXP.Value
	
	local currentExp = currentExpTotal - previousExp
	local neededExp = nextExp - previousExp
	
	local textToDisplay = currentExp .. "/" .. neededExp
	expText.Text = textToDisplay
	
	local scaleX = currentExp / neededExp
	local inverseScaleX = scaleX > 0 and 1/scaleX or 0
	
	local goalClipping = {Size = UDim2.new(scaleX, 0, 1, 0)}
	local goalBar = {Size = UDim2.new(inverseScaleX, 0, 1, 0)}
	
	local tweenDuration = math.clamp(math.abs(scaleX - barClipping.Size.X.Scale), 0, 0.7)
	local tweenInfo = TweenInfo.new(tweenDuration, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
	
	local tweenClipping = tweenService:Create(barClipping, tweenInfo, goalClipping)
	tweenClipping:Play()
end

function OnLevelChanged()

	local currentLevel = plrLVL.Value
	local nextLevel = currentLevel + 1

	local currentToDisplay = prefix .. currentLevel
	local nextToDisplay = prefix .. nextLevel

	currentLevelText.Text = currentToDisplay
	nextLevelText.Text = nextToDisplay
end

OnExpChanged()
OnLevelChanged()

plrEXP:GetPropertyChangedSignal("Value"):Connect(OnExpChanged)
plrLVL:GetPropertyChangedSignal("Value"):Connect(OnLevelChanged)


local lastLeveledUp = 0

function OnLevelUp()
	
	local now = tick()
	lastLeveledUp = now
	
	local previousLevel = plrLVL.Value - 1
	local currentLevel = previousLevel + 1
	
	local previousToDisplay = prefix .. previousLevel
	local currentToDisplay = prefix .. currentLevel
	
	local textToDisplay = "<font size = '10' color='rgb(135, 135, 135)'>" .. previousToDisplay .. "→</font> <font color='rgb(255,162,32)'>" .. currentToDisplay .."</font>"
	levelUpText.Text = textToDisplay
	
	ShowLevelUp()
	
	task.wait(5)
	
	if levelUpGui.Enabled == true and lastLeveledUp == now then
		
		HideLevelUp()
	end
end

function ShowLevelUp()
	
	local started = tick()
	
	levelUpBG.BackgroundTransparency = 1
	levelUpTitle.TextTransparency = 1
	levelUpText.TextTransparency = 1

	local levelUpTextPos = UDim2.new(0.5, 0, 0.5, 0)
	local levelUpTextSize = UDim2.new(0.62, 0, 0.118, 0)

	levelUpText.Position = levelUpTextPos + UDim2.new(0, 0, 0.1, 0)
	levelUpText.Size = levelUpTextSize - UDim2.new(0.2, 0, 0.2, 0)

	levelUpGui.Enabled = true
	
	levelUpGui.LevelUpSound:Play()

	local tweenInfo = TweenInfo.new(0.6, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)

	local bgTween = tweenService:Create(levelUpBG, tweenInfo, {BackgroundTransparency = 0.1})
	bgTween:Play()

	local titleTween = tweenService:Create(levelUpTitle, tweenInfo, {TextTransparency = 0})
	titleTween:Play()

	task.wait(0.1)
	
	if levelUpGui.Enabled == true and started > lastLeveledUp then
		
		local textTween = tweenService:Create(levelUpText, tweenInfo, {TextTransparency = 0, Position = levelUpTextPos, Size = levelUpTextSize})
		textTween:Play()
	end
end

function HideLevelUp()
	
	local started = tick()
	
	local tweenInfo = TweenInfo.new(0.6, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
	
	local textTween = tweenService:Create(levelUpText, tweenInfo, {TextTransparency = 1})
	textTween:Play()
	
	task.wait(0.2)
	
	if levelUpGui.Enabled == true and started > lastLeveledUp then
		
		local bgTween = tweenService:Create(levelUpBG, tweenInfo, {BackgroundTransparency = 1})
		bgTween:Play()

		local titleTween = tweenService:Create(levelUpTitle, tweenInfo, {TextTransparency = 1})
		titleTween:Play()
		
		titleTween.Completed:Wait()
		
		levelUpGui.Enabled = false
	end
end

levelUpBG.MouseButton1Click:Connect(HideLevelUp)

levelUpRE.OnClientEvent:Connect(OnLevelUp)
``

local CalculateStats = require(replicatedModules:WaitForChild("CalculateStats"))

We need to see this in order to see how you are calculating your stats. Your calculations could be wrong and just making it 0 or nil, if you try to forcefully set Level to 5 does it save?

function Local.LoadProfile(player : Player)
	local profile = PlayerStore:StartSessionAsync(`{player.UserId}`, {
		Cancel = function()
			return player.Parent ~= Players
		end,
	})
	
	if profile == nil then
		return player:Kick("ProfileStore Error 1: No data profile found. Try rejoining the game")
	end
	
	profile:AddUserId(player.UserId)
	profile:Reconcile()
	
	profile.OnSessionEnd:Connect(function()
		Profiles[player] = nil
		player:Kick("Profile seasion ended. Try rejoining")
	end)
	
	local inGame = player.Parent == Players
	if inGame then
		Profiles[player] = profile
		
		
		ProfileStats.New(player)
		ProfileStats.SetStats(player, profile.Data.Level, profile.Data.Exp)
		
		while true do
			task.wait(1)
			profile.Data.Level += 1 -- Add 1 to level every second
			print("Leaderstats: ", player.STATS.Level.Value)
			print("Profile.Data: ", profile.Data.Level)
		end
	else
		profile:EndSession()
	end
end

I think its weird that im always getting zero for leaderstats, but for Profile.Data its increasing

Yeah its saving but if i remove its not saving

It’s because you are never directly setting the levelValue.Value = profile.Data.Level when the player levels up so it stays as 0 for the .Value, add that code where ever you update the level make sure it is on the servers side.

If it is saving correctly through profile.Data.Level that means everything is setup and the only issue wrong is most likely you never update the value as said above.

Thanks for reply, i tried doing it like this ``` Players.PlayerAdded:Connect(function (player)
local profile = Data.GetData(player)

player.STATS.Lvl.Value = profile.Data.Level
player.STATS.EXP.Value = profile.Data.Exp

end)```

but its not working

function Local.LoadProfile(player : Player)
	local profile = PlayerStore:StartSessionAsync(`{player.UserId}`, {
		Cancel = function()
			return player.Parent ~= Players
		end,
	})
	
	if profile == nil then
		return player:Kick("ProfileStore Error 1: No data profile found. Try rejoining the game")
	end
	
	profile:AddUserId(player.UserId)
	profile:Reconcile()
	
	profile.OnSessionEnd:Connect(function()
		Profiles[player] = nil
		player:Kick("Profile seasion ended. Try rejoining")
	end)
	
	local inGame = player.Parent == Players
	if inGame then
		Profiles[player] = profile
		
		
		ProfileStats.New(player)
		ProfileStats.SetStats(player, profile.Data.Level, profile.Data.Exp)
		
		while true do
			task.wait(1)
			profile.Data.Level += 1 -- Add 1 to level every second
			player.Stats.Level.Value = profile.Data.Level
			print("Leaderstats: ", player.STATS.Level.Value)
			print("Profile.Data: ", profile.Data.Level)
		end
	else
		profile:EndSession()
	end
end

Could you try this in the loop i added it updates the value as well. If this works you need to set the player’s value everytime the level is updated. So where you call ModuleName.LevelUp(Player: Player) you need to set the Player.STATS.Level.Value = profile.Data.Level

2 Likes

Thank you so much, it worked, tysmmmmmmmm

1 Like

You’re welcome, Good Luck on your project!

Also i have a question, if i set this in loop will it change game perfomance and how i can do it without loop?

Well if you could supply the function where you update the player’s level that can help me assist you. You shouldn’t need to run it in a loop at all. Only call it when the player meets requirements to level up judging by your code you supplied you have Exp so you can check if they meet the Exp Requirement for the next level?