Weird jumping in NumberValues

Hello! I have a script I’m writing to basically create my own mining system, and I’ve posted about this before asking help for different parts of the script but I thought I should make a separate post for this issue. Basically what I have working is several pieces in a mesh I made fly apart into individual segments, which you can then click on to ‘pick up’. When you pick up a piece, a NumberValue stored within a folder within the player gets raised by one, then the value is displayed on a TextLabel. I also have another Gui where you can ‘craft’ items using the value on the NumberValue. Here’s a gif depicting what I mean:

However, whenever I craft things it seems like the value is going down, and from the tests I’ve done (with basic print functions) it actually is decreasing, but after I finish ‘crafting’ and I go to pick up another piece of the mesh, the value seems to jump up to the amount I had before crafting. Here’s a demonstration: (Keep your eye on the value of ‘Rock’)

To be frank, I honestly am completely stumped. I have no clue as to what’s causing this to happen, but my best guess has to do with the script that raises the value of the NumberValue. Here is the script for that: (Server script)

local rock = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage")
local event = replicatedStorage:WaitForChild("Event")
local health = script.Parent.Health
local label = script.Parent.BillboardGui.TextLabel
local class = script.Parent.Class.Value

local function breakup(plr)
	for i,v in pairs(rock:GetChildren()) do
		if v:IsA('BasePart') then --Run only on parts
			v.Anchored = false
			v.Velocity = Vector3.new(math.random(-20,20), math.random(-20,20),math.random(-20,20))
		end
	end
end

local function setupRemovalRock()
    for i,v in pairs(rock:GetChildren()) do
	    if v:IsA ('BasePart') then
		    v.ClickDetector.MouseClick:Connect(function(plr) --This is the part that let's me pickup the pieces.
				local stats = plr:WaitForChild("Stats")
				stats.Rock.Value = stats.Rock.Value + 1
				v:Destroy()
		    end)
	    end
    end
end

event.OnServerEvent:Connect(function()
	health.Value = health.Value - 1
end)

health.Changed:Connect(function()
	if health.Value == 0 then --Here we reference the value, as it remaining constant doesn't matter
		breakup()
		label.Visible = false
        setupRemovalRock()
	else
		label.Text = ("Health: "..health.Value)
	end
end)

--Script made by gameyall232 with help from REALTimothy0812.

And here is a screenshot of where the script is in the game:


Thank you so much for reading!
Oh, and if you need any more information at all I’d be happy to provide it for you!

The script above looks fine. The only thing i could think of is when you craft something do you subtract the number from

plr:WaitForChild("Stats").Rock

or do you subtract it from the player gui?

Is the value changed only on the server? If it was changed on the client, this would happen due to them not being synced.

Also, could you attach the code for crafting? It will help a lot.

In response to both @D3vKing and @REALTimothy0812, I think that’s the issue. I use a LocalScript in the crafting menu GUI to subtract from their value. Should I make another Server script inside the GUI to do the subtraction or should I put it somewhere else?

Also sorry for the late response, I had to go to sleep. Also, I have to go to school now, so I might not respond soon again.

Here’s the script for the crafting: It’s a LocalScript.

local stats = game.Players.LocalPlayer:WaitForChild("Stats")
local rock = stats.Rock

for i,v in pairs (script.Parent:GetChildren()) do
	if v:IsA("Frame") then
		v.TextButton.MouseButton1Click:Connect(function()
			if rock.Value > 0 and v.TextButton.Text == ("Craft") then
				local price = v.Price.Value
				rock.Value = rock.Value - price
				
			else
				v.TextButton.Text = ("Not Enough!")
				wait(1)
				v.TextButton.Text = ("Craft")
			end
		end)
	end
end

That is the problem you need to send the information to the server. Right now it is just subtracting it on the client but the value on the server remains the same. If you want to return the words “Not Enough!” or “Craft” you would need to use a Remote Function. There is a video about it here.

I’d like to detail this problem a bit more:

  • Client removed from value
  • Server adds to value. From its point of view, the client did nothing. So the server adds 1 to the “old” value.
  • Client gets replication from server, and updates the value to the servers one.

Basically, just do any value changing on the server. The only things you should do on the client is character physics, input, sending that input, and displaying values.