Why is my ProfileStore not working ingame

I have a system which saves animals with the player and tools etc. It works perfectly in studio however in the game sometimes it refuses to save and doesn’t work and doesnt load. It was temporarily fixed by adding task.wait(0.5) but now its just not saving again. I am very confused.

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

local ProfileStore = require(ServerScriptService.Libraries.ProfileStore)
local Template = require(ServerScriptService.Data.Template)
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local playerStore = ProfileStore.New("HuntTest5", Template)
local DataManager = require(ServerScriptService.Data.DataManager)
local playerEquippedCache = {} 

local AnimalStats = require(game.ReplicatedStorage.AnimalStatsModule)
local Mutations = require(game.ReplicatedStorage.MutationStatsModule)

local Bestiary = {}

local function applyMutation(mutation, animal)
	for i, fx in pairs(ReplicatedStorage.MutationFX[mutation]:GetChildren()) do
		if fx:IsA("ParticleEmitter") then
			fx:Clone().Parent = animal.PrimaryPart
		end
	end

	for i, parts in pairs(animal:GetDescendants()) do
		if parts:IsA("UnionOperation") or parts:IsA("MeshPart") or parts:IsA("BasePart") then


			if ReplicatedStorage.MutationFX[mutation]:FindFirstChild("ColourMultiply") then
				local color_1 = parts.Color
				local color_2 = ReplicatedStorage.MutationFX[mutation].ColourMultiply.Value
				local alpha = ReplicatedStorage.MutationFX[mutation].Alpha.Value

				local mixed_color = color_1:Lerp(color_2, alpha)


				parts.Color = mixed_color
			end

			if mutation == "Glow" or mutation == "Celestial" or mutation == "Void" then
				parts.Material = Enum.Material.Neon
			end

			if mutation == "Spirit" then
				if parts.Transparency == 0 then
					parts.Transparency = 0.5
				end

			end

		end


	end


end


local function applyStats(animal, name, weight)

	local weight = weight

	local minWeight = AnimalStats[name].Weight.min
	local maxWeight = AnimalStats[name].Weight.max


	local scaleFactor = 1 + (weight - minWeight) / (maxWeight - minWeight) * (1.8 - 0.85)


	animal:ScaleTo(scaleFactor)



	animal:WaitForChild("Humanoid").WalkSpeed = animal:WaitForChild("Values"):WaitForChild("Speed").Value
end

local function createAnimal(plr, animaldata)
	if plr and animaldata then

		local regionFolder = game.ReplicatedStorage.Animals:WaitForChild(animaldata.Region)
		local Dummy = regionFolder:WaitForChild(animaldata.Animal):Clone()
		
		if Dummy:FindFirstChild("Pathfinding") then
			Dummy:FindFirstChild("Pathfinding"):Destroy()
		end


		local tool = Instance.new("Tool")

		applyStats(Dummy, animaldata.Animal, animaldata.Weight)
		applyMutation(animaldata.Mutation, Dummy)



		local size = Dummy:GetExtentsSize()
		local largestDimension = math.max(size.X, size.Y, size.Z)


		local distanceOffset = largestDimension * 0.2
		local heightOffset = -size.Y * 0.25   
		local sideOffset = 0                

		tool.Grip = CFrame.new(distanceOffset, heightOffset, sideOffset) * CFrame.Angles(0, math.rad(90), 0)



		if animaldata.Mutation ~= "None" then
			tool.Name = animaldata.Mutation .. " " .. Dummy.Name
		else
			tool.Name = animaldata.Animal
		end

		tool.CanBeDropped = false
		


		for i, children in pairs(Dummy:GetChildren()) do
			children.Parent = tool

			if children.Name == "HumanoidRootPart" then
				children.Name = "Handle"
				children.CanTouch = false
			end

			if children:IsA("MeshPart") or children:IsA("BasePart") or children:IsA("UnionOperation") then
				children.Massless = true
				children.CanCollide = false

			end

			if children:IsA("Humanoid") then
				children:Destroy()
			end




		end

		tool:WaitForChild("Values"):WaitForChild("Animal").Value = animaldata.Animal
		tool:WaitForChild("Values"):WaitForChild("Despawn").Value = animaldata.Despawn
		tool:WaitForChild("Values"):WaitForChild("Health").Value = animaldata.Health
		tool:WaitForChild("Values"):WaitForChild("Mutation").Value = animaldata.Mutation
		tool:WaitForChild("Values"):WaitForChild("Price").Value = animaldata.Price
		tool:WaitForChild("Values"):WaitForChild("Range").Value = animaldata.Range
		tool:WaitForChild("Values"):WaitForChild("Rarity").Value = animaldata.Rarity
		tool:WaitForChild("Values"):WaitForChild("RarityTier").Value = animaldata.RarityTier
		tool:WaitForChild("Values"):WaitForChild("Speed").Value = animaldata.Speed
		tool:WaitForChild("Values"):WaitForChild("Weight").Value = animaldata.Weight
		tool:WaitForChild("Values"):WaitForChild("Region").Value = animaldata.Region
		tool:WaitForChild("Values"):WaitForChild("Damage").Value = animaldata.Damage
		tool:WaitForChild("Values"):WaitForChild("Quality").Value = animaldata.Quality
		
		tool.ToolTip = animaldata.Weight .. "kg"


		tool.Parent = plr.Backpack

		tool:FindFirstChild("HealthGUI"):Destroy()

	elseif not animaldata then
		local data = {}

		plr.AnimalData = data

	end
end

local function initialize(player : Player, profile : typeof(playerStore:StartSessionAsync()))
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local PlayerValues = Instance.new("Folder", player)
	PlayerValues.Name = "PlayerValues"
	
	local AvailableHealth = Instance.new("NumberValue", PlayerValues)
	AvailableHealth.Name = "AvailableHealth"
	AvailableHealth.Value = profile.Data.AvailableHealth
	
	local HealAmount = Instance.new("NumberValue", PlayerValues)
	HealAmount.Name = "HealAmount"
	HealAmount.Value = profile.Data.HealAmount
	
	local HealInterval = Instance.new("NumberValue", PlayerValues)
	HealInterval.Name = "HealInterval"
	HealInterval.Value = profile.Data.HealInterval
	
	local Islands = Instance.new("StringValue", PlayerValues)
	Islands.Name = "Island"
	Islands.Value = profile.Data.Island
	
	
	
	local Coins = Instance.new("NumberValue", leaderstats)
	Coins.Name = "Coins"
	Coins.Value = profile.Data.Coins
	
	if game.ReplicatedStorage.Guns:FindFirstChild(profile.Data.EquippedGun) then
		game.ReplicatedStorage.Guns:FindFirstChild(profile.Data.EquippedGun):Clone().Parent = player.Backpack
	else
		game.ReplicatedStorage.Guns:FindFirstChild("Basic Gun"):Clone().Parent = player.Backpack
	end

	if game.ReplicatedStorage.Nets:FindFirstChild(profile.Data.EquippedNet) then
		game.ReplicatedStorage.Nets:FindFirstChild(profile.Data.EquippedNet):Clone().Parent = player.Backpack
	else
		game.ReplicatedStorage.Nets:FindFirstChild("Basic Net"):Clone().Parent = player.Backpack
	end
	
	game.ReplicatedStorage.Events.UpdateEquippedGuns:FireClient(player, profile.Data.EquippedGun)
	game.ReplicatedStorage.Events.UpdateEquippedNets:FireClient(player, profile.Data.EquippedNet)
	
	game.ReplicatedStorage.Events.UpdateGuns:FireClient(player, profile.Data.GunsOwned)
	game.ReplicatedStorage.Events.UpdateNets:FireClient(player, profile.Data.NetsOwned)
	
	
	for _, animalData in ipairs(profile.Data.Animals) do
		createAnimal(player, animalData)

		print(animalData)
	end
	
	local actualHealth = Instance.new("NumberValue")
	actualHealth.Name = "ActualHealth"
	actualHealth.Parent = player
	actualHealth.Value = profile.Data.AvailableHealth
	
	local IsImmune = Instance.new("BoolValue")
	IsImmune.Name = "IsImmune"
	IsImmune.Parent = player
	IsImmune.Value = false
	
	local IsInMiniGame = Instance.new("BoolValue")
	IsInMiniGame.Name = "IsInMiniGame"
	IsInMiniGame.Parent = player
	IsInMiniGame.Value = false
	
	
	game.ReplicatedStorage.Events.UpdateCoins:FireClient(player, profile.Data.Coins)
	
	
	
	

	for _, regionFolder in pairs(ReplicatedStorage.Animals:GetChildren()) do
		for _, animal in pairs(regionFolder:GetChildren()) do
			local entry = profile.Data.Bestiary[animal.Name]
			if not entry then
				profile.Data.Bestiary[animal.Name] = {
					Region = regionFolder.Name,
					Name = animal.Name,
					Captured = false,
					HighestWeight = 0,
				}
				
			else
				print("Animal Already in Bestiary")
			end
			
		end
	end
	
	print(profile.Data.Bestiary)
	
	game.ReplicatedStorage.Events.UpdateBestiary:FireClient(player, profile.Data.Bestiary)
	
	

	
	
	
	
end

local function serializeAnimal(tool)
	return {
		Animal = tool:WaitForChild("Values"):WaitForChild("Animal").Value,
		Despawn = tool:WaitForChild("Values"):WaitForChild("Despawn").Value,
		Health = tool:WaitForChild("Values"):WaitForChild("Health").Value,
		Mutation = tool:WaitForChild("Values"):WaitForChild("Mutation").Value,
		Price = tool:WaitForChild("Values"):WaitForChild("Price").Value,
		Range = tool:WaitForChild("Values"):WaitForChild("Range").Value,
		Rarity = tool:WaitForChild("Values"):WaitForChild("Rarity").Value,
		RarityTier = tool:WaitForChild("Values"):WaitForChild("RarityTier").Value,
		Speed = tool:WaitForChild("Values"):WaitForChild("Speed").Value,
		Weight = tool:WaitForChild("Values"):WaitForChild("Weight").Value,
		Region = tool:WaitForChild("Values"):WaitForChild("Region").Value,
		Damage = tool:WaitForChild("Values"):WaitForChild("Damage").Value,
		Quality = tool:WaitForChild("Values"):WaitForChild("Quality").Value
	}
end

local function playerAdded(player : Player)
	local Profile = playerStore:StartSessionAsync("Player_" .. player.UserId, {
		Cancel = function()
			return player.Parent ~= Players
		end,
	})
	
	if Profile ~= nil then
		
		Profile:AddUserId(player.UserId)
		Profile:Reconcile()
		
		Profile.OnSessionEnd:Connect(function()
			DataManager.Profiles[player] = nil
			player:Kick("Datastore error. Please rejoin.")
		end)
		
		if player.Parent == Players then
			
			DataManager.Profiles[player] = Profile
			
			initialize(player, Profile)
			
		else
			Profile:EndSession()
		end
		
		
	else
		player:Kick("Datastore error. Please rejoin.")
	end
end



local function AddAnimals(player)
	
	local animalsTable = {}

	if player then



		for _, tool in pairs(player.Backpack:GetChildren()) do

			if tool:IsA("Tool") then
				local values = tool:FindFirstChild("Values")
				local isAnimal = values and values:FindFirstChild("IsAnAnimal")
				if isAnimal then
					table.insert(animalsTable, serializeAnimal(tool))
				end
			end
		end

		if playerEquippedCache[player.UserId] then
			for i, v in pairs(playerEquippedCache[player.UserId]) do
				table.insert(animalsTable, serializeAnimal(v))
			end

			playerEquippedCache[player.UserId] = nil
		end
		
		
		print(animalsTable)
		
		if animalsTable then
			DataManager.AddAnimals(player, animalsTable)
		end
		

	end
	
end

Players.PlayerAdded:Connect(playerAdded)

for i,plr in Players:GetPlayers() do
	task.spawn(playerAdded, plr)
end


Players.PlayerRemoving:Connect(function(plr)
	
	AddAnimals(plr)
	local Profile = DataManager.Profiles[plr]
	
	if not Profile then return end
	
	task.wait(0.5)
	
	Profile:EndSession()
	DataManager.Profiles[plr] = nil
end)

game:BindToClose(function()
	for i,plr in Players:GetPlayers() do
		
		AddAnimals(plr)
		local Profile = DataManager.Profiles[plr]

		if not Profile then return end
		
		task.wait(0.5)

		Profile:EndSession()
		DataManager.Profiles[plr] = nil
	end
end)

ReplicatedStorage.Events.CacheToolInHand.OnServerEvent:Connect(function(plr, tool, equipped)

	if not playerEquippedCache[plr.UserId] then
		playerEquippedCache[plr.UserId] = {}
	end

	if equipped == true then

		if not table.find(playerEquippedCache[plr.UserId], tool) then
			table.insert(playerEquippedCache[plr.UserId], tool)
		end
	elseif equipped == false then

		for i, t in ipairs(playerEquippedCache[plr.UserId]) do
			if t == tool then
				table.remove(playerEquippedCache[plr.UserId], i)
				break
			end
		end
	end
end)

Im super confused, thanks. I believe its not loading either. Its also worth noting the bestiary loads? When I was testing in game I got kicked for Datastore error. Please rejoin which is fired when profile is nil in my script or session end…
what is going on.

1 Like

I assume you’ve seen RileyBytes’ tutorial on setting up ProfileStore…
I’d say that it’s just…as it says, a data store error. Have you considered that you may have saved something which shouldn’t have been saved? For example, an Instance, a table of mixed keys, a table of number keys with gaps?

1 Like

Furthermore, I think you’d find it easier to work with more tables so that you don’t have to manually do stuff like “Islands.Name” = “Island” and you could then just change the constant variables whenever you like

Try adding print statements across your code to make sure that information is being passed between functions properly because that tends to be the problem for me

1 Like

Would you believe it.. it was me not waiting for the character to load…

	local character = player.Character or player.CharacterAdded:Wait()
	local backpack = player:WaitForChild("Backpack")

ig this is the problem with handling tools in saving and loading.. Thanks for the help.

Hey! At least you found it! The importance of :Wait() and :WaitForChild()!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.