Why won't these ObjectValues save?

Hello, fellow developers. Today I added ObjectValues to my leaderstats folder to save the player’s loadout. I know for a fact that it isn’t a problem with how the loadout is handled, because it does add the preset tools set in the leaderstats and does change the tools if you select a different one. However, it doesn’t even change the values when the player selects a different tool, and when I manually change the values, it doesn’t even save them. It doesn’t throw any errors or anything like that. Am I saving it right? Can I even save ObjectValues? Any help would be greatly appreciated.

Edit: The Cash, Level, and Exp stats work and save perfectly fine, it’s just the Primary, Secondary, and Melee ObjectValues that are the problem.

The scripts if needed

The leaderstats script in ServerScriptService:

local DataStoreService = game:GetService("DataStoreService")
local CashDataStore = DataStoreService:GetDataStore("Cash")
local LevelDataStore = DataStoreService:GetDataStore("Level")
local ExpDataStore = DataStoreService:GetDataStore("Exp")
local PrimaryDataStore = DataStoreService:GetDataStore("Primary")
local SecondaryDataStore = DataStoreService:GetDataStore("Secondary")
local MeleeDataStore = DataStoreService:GetDataStore("Melee")

function incrementExp(player, increment)

	for i = player.leaderstats.Exp.Value, player.leaderstats.Exp.Value + increment do

		player.leaderstats.Exp.Value = i

		wait()
	end
end

game.Players.PlayerAdded:Connect(function(Player)
	local Leaderstats = Instance.new("Folder", Player)
	Leaderstats.Name = "leaderstats"

	local Cash = Instance.new("IntValue", Leaderstats)
	Cash.Name = "Cash" 
	Cash.Value = 0
	
	local Level = Instance.new("IntValue", Leaderstats)
	Level.Name = "Level"
	Level.Value = 1

	local Exp = Instance.new("IntValue", Leaderstats)
	Exp.Name = "Exp"
	Exp.Value = 0
	
	local Primary = Instance.new("ObjectValue", Leaderstats)
	Primary.Name = "Primary"
	Primary.Value = game.ReplicatedStorage.Weapons.Primary.M4A1
	
	local Secondary = Instance.new("ObjectValue", Leaderstats)
	Secondary.Name = "Secondary"
	Secondary.Value = game.ReplicatedStorage.Weapons.Secondary["Beretta M9"]
	
	local Melee = Instance.new("ObjectValue", Leaderstats)
	Melee.Name = "Melee"
	Melee.Value = game.ReplicatedStorage.Weapons.Melee.BAYONET

	local CashData = CashDataStore:GetAsync(Player.UserId)
	if CashData then
		Cash.Value = CashData.Cash
	end
	
	local LevelData = LevelDataStore:GetAsync(Player.UserId)
	if LevelData then
		Level.Value = LevelData.Level
	end
	
	local ExpData = ExpDataStore:GetAsync(Player.UserId)
	if ExpData then
		Exp.Value = ExpData.Exp
	end
	
	local PrimaryData = PrimaryDataStore:GetAsync(Player.UserId)
	if PrimaryData then
		Primary.Value = PrimaryData.Primary
	end

	local SecondaryData = SecondaryDataStore:GetAsync(Player.UserId)
	if SecondaryData then
		Secondary.Value = SecondaryData.Secondary
	end

	local MeleeData = MeleeDataStore:GetAsync(Player.UserId)
	if MeleeData then
		Melee.Value = MeleeData.Melee
	end
	
	Exp:GetPropertyChangedSignal("Value"):Connect(function()
		local neededExp = math.floor(Level.Value ^ 1.5 + 0.5) * 500

		if Exp.Value >= neededExp then
			Level.Value += 1
		end
	end)
end)


game.Players.PlayerRemoving:Connect(function(Player)
	CashDataStore:SetAsync(Player.UserId, {
		["Cash"] = Player.leaderstats.Cash.Value;
	})
	
	LevelDataStore:SetAsync(Player.UserId, {
		["Level"] = Player.leaderstats.Level.Value;
	})
	
	ExpDataStore:SetAsync(Player.UserId, {
		["Exp"] = Player.leaderstats.Exp.Value;
	})
	PrimaryDataStore:SetAsync(Player.UserId, {
		["Primary"] = Player.leaderstats.Primary.Value;
	})

	SecondaryDataStore:SetAsync(Player.UserId, {
		["Secondary"] = Player.leaderstats.Secondary.Value;
	})

	MeleeDataStore:SetAsync(Player.UserId, {
		["Melee"] = Player.leaderstats.Melee.Value;
	})
end)

The LoadoutHandler local script inside loadout GUI:

local weaponsFolder = game.ReplicatedStorage:WaitForChild("Weapons")
local weaponTypes = {weaponsFolder.Primary, weaponsFolder.Secondary, weaponsFolder.Melee}
local player = game.Players.LocalPlayer

local loadout = script.Parent:WaitForChild("Loadout")

--These are the preset loadouts, this isn't permanent!
local primary = player.leaderstats.Primary.Value
local secondary = player.leaderstats.Secondary.Value
local melee = player.leaderstats.Melee.Value

local primaryText = loadout.PrimaryFrame:WaitForChild("PrimaryText")
local secondaryText = loadout.SecondaryFrame:WaitForChild("SecondaryText")
local meleeText = loadout.MeleeFrame:WaitForChild("MeleeText")


local function updateLoadout()
	if primary then
		primaryText.Text = "Primary - " .. primary.Name
		game.ReplicatedStorage.Remotes.EquipWeaponRE:FireServer(primary)
	end

	if secondary then
		secondaryText.Text = "Secondary - " .. secondary.Name
		game.ReplicatedStorage.Remotes.EquipWeaponRE:FireServer(secondary)
	end

	if melee then
		meleeText.Text = "Melee - " .. melee.Name
		game.ReplicatedStorage.Remotes.EquipWeaponRE:FireServer(melee)
	end
end
updateLoadout()


for i, weaponType in pairs(weaponTypes) do

	local newButton = script.WeaponTypeButton:Clone()
	newButton.Text = weaponType.Name

	newButton.Parent = loadout.WeaponTypes


	newButton.MouseButton1Click:Connect(function()

		for i, child in pairs(loadout.WeaponsList:GetChildren()) do

			if child:IsA("TextButton") then child:Destroy() end
		end


		for i, weaponChild in pairs(weaponType:GetChildren()) do

			local newWeaponButton = script.WeaponButton:Clone()
			newWeaponButton.Text = weaponChild.Name

			newWeaponButton.Parent = loadout.WeaponsList


			newWeaponButton.MouseButton1Click:Connect(function()

				if weaponType.Name == "Primary" then
					primary = weaponChild

				elseif weaponType.Name == "Secondary" then
					secondary = weaponChild

				elseif weaponType.Name == "Melee" then
					melee = weaponChild
				end

				updateLoadout()
			end)
		end
	end)
end

game.Players.LocalPlayer.CharacterAdded:Connect(function()
	updateLoadout()
end)

The WeaponEquipper script located inside ServerScriptService:

local weapons = game.ReplicatedStorage:WaitForChild("Weapons")
local re = game.ReplicatedStorage.Remotes:WaitForChild("EquipWeaponRE")

re.OnServerEvent:Connect(function(plr, gun)
	if gun and gun.Parent.Parent == weapons then
		local gunType = gun.Parent
		
		for i, child in pairs(plr.Backpack:GetChildren()) do
			
			if gunType:FindFirstChild(child.Name) then
				child:Destroy()
			end
		end
		
		for i, child in pairs(plr.Character:GetChildren()) do

			if gunType:FindFirstChild(child.Name) then
				child:Destroy()
			end
		end
		
		
		local gunClone = gun:Clone()
		gunClone.Parent = plr.Backpack
		if gunType == "Primary" then
			plr.leaderstats.Primary.Value = gun
		elseif gunType == "Secondary" then
			plr.leaderstats.Secondary.Value = gun
		elseif gunType == "Melee" then
			plr.leaderstats.Melee.Value = gun
		end
	end
end)

Thanks,
SpeakerDev

Can you send a vid of this in action?

It won’t send, I’ll have to fix this and try again tomorrow

As far as I’m aware you can’t save Object Values to DataStores. You would have to store the value names as a reference - Melee.Value.Name

Object values are NOT savable, save their names and load them from where you have all the items by their names

Could you give a topic I can reference regarding this? I’m not sure how to do this.