Part moving on the server but not the client

I’m making a tycoon game and have a ore spawner which is meant to move on a conveyor belt which uses velocity to move parts.

The only problem with it is that, the parts only move on the server but they don’t move for the client.

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local TycoonFolder = script.Parent.Parent
local Ores = ReplicatedStorage.Ores
local Droppers = TycoonFolder.Droppers

local SPAWN_TIME = 1

local IronOre = Ores["Iron Ore"]

local function spawnOre(Dropper: Model, Ore: string)
	for _, part in pairs(Dropper:GetChildren()) do
		if part.Name == "Output" then
			local Spawner: BasePart = part:FindFirstChild("Spawner")
			if Spawner then
				if Ore == "Iron" then

						local ClonedIron = IronOre:Clone()

						ClonedIron.Parent = workspace
						ClonedIron.Anchored = false
						ClonedIron:SetNetworkOwner(nil)
						ClonedIron.Position = (Spawner.Position - Vector3.new(0, 0.6, 0)) 
						print(ClonedIron:GetNetworkOwner())
						print(ClonedIron.Anchored)
				end
			end
		end
		
	end
end

task.spawn(function()
	while true do
		task.wait(1)
		for _, dropper in pairs(Droppers:GetChildren()) do
			if dropper:IsA("Model") then
				spawnOre(dropper, "Iron")
				print("added")
			end
		end
	end
end)

Client:


Server:

You can read more on network ownership here.

This is not something that’s so critical that you’d need the server to be in control. An exploiter moving these parts around could either get the parts to their destination faster, or do the opposite of that.

The former shouldn’t be a concern - they might get their points quicker, but this doesn’t affect the drop rate (assuming you weren’t planning on scripting it in that way).

The latter may be a concern, if they keep so many parts in workspace as to cause lag, and you can prevent this using Debris, to remove the items after a certain amount of time you approximate as good. Now, messing with the parts can only cause them to not get their points because the parts didn’t reach their destination.

So yeah, I’d say give network ownership to the “owner” of those droppers, and do either Debris:AddItem(Part, x) or task.delay(x, Part.Destroy, Part), “x” being the amount of time in seconds.

This didn’t work and it made the blocks stay in one place.

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local TycoonFolder = script.Parent.Parent
local Ores = ReplicatedStorage.Ores
local Droppers = TycoonFolder.Droppers

local SPAWN_TIME = 1

local IronOre = Ores["Iron Ore"]

local function spawnOre(Dropper: Model, Ore: string)
	for _, part in pairs(Dropper:GetChildren()) do
		if part.Name == "Output" then
			local Spawner: BasePart = part:FindFirstChild("Spawner")
			if Spawner then
				if Ore == "Iron" then
						local ClonedIron = IronOre:Clone()

						ClonedIron.Parent = workspace
						ClonedIron.Size = Vector3.one
						ClonedIron.Anchored = false
						ClonedIron:SetNetworkOwner(game.Players:FindFirstChild(script.Parent.Parent.Values.Owner.Value))
						ClonedIron.Position = (Spawner.Position - Vector3.new(0, 0.6, 0)) 
						print(ClonedIron:GetNetworkOwner())
						print(ClonedIron.Anchored)
						task.delay(5, ClonedIron.Destroy, ClonedIron)
				end
			end
		end
	end
end

task.spawn(function()
	while true do
		task.wait(3)
		for _, dropper in pairs(Droppers:GetChildren()) do
			if dropper:IsA("Model") then
				spawnOre(dropper, "Iron")
				print("added")
			end
		end
	end
end)

And the two prints are printing correct values?

Yes, they print, the player and false

Interesting, I will check in Studio later when I’m free, if someone doesn’t reply with a solution by then.