Pickaxe speed is faster than intended in Roblox and is the right speed in Studio

I am working on an infinite mining game, but I am encountering a weird bug where the pickaxe is too fast in Roblox but at the normal speed in Studio.

Video of how fast the pickaxe is supposed to be (Studio):

Video of how fast the pickaxe shouldn’t be (Roblox):

The speed is determined by an attribute inside the tool and a value inside a table.

Attribute inside the tool: img-2024-05-01-18-16-32

Speed value inside the table:

local blockProperties = {
	[1] = {
		["Speed"] = 0.05, --Speed Value
		["Strength"] = 0,
		["Value"] = 2,
	},
	
	[2] = {
		["Speed"] = 0.05, --Speed Value
		["Strength"] = 0,
		["Value"] = 1,
	},
}

This is how the progress bar moves depending on the speed:

bar.Position += UDim2.new(Speed*toolSpeed,0,0,0)

Prob for anyone to help we would at least need to see the script that is swinging the pickaxe and how these values are used…

things in general might be slower in studio and faster when you play the game with out the studio overhead… my thought… but the first part above would help unless you want us to guess…

This is the script that handles the pickaxe swinging (localscript)

local tool = script.Parent
local objValue = tool:WaitForChild("SelectedPart")

local collectionService = game:GetService("CollectionService")
local runService = game:GetService("RunService")

local anim = Instance.new("Animation")
anim.Name = "UseAnim"
anim.AnimationId = "rbxassetid://16947394662"
local track

local State = false
local mineDebounce = false

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
mouse.TargetFilter = workspace.Cubes.Invisible

local pgui = player:WaitForChild("PlayerGui")
local gui = pgui:WaitForChild("MiningGui")
local bar = gui.Frame.Bar.Green

local selection = workspace.SelectionBox

local toolSpeed = tool:GetAttribute("Speed")
local toolStrength = tool:GetAttribute("Strength")
local Speed
local Strength
local Value

local lastTarget

tool.Equipped:Connect(function()
	track = script.Parent.Parent.Humanoid.Animator:LoadAnimation(anim)
	track.Priority = Enum.AnimationPriority.Movement
end)

tool.Unequipped:Connect(function()
	if track then
		track:Stop()
	end
	selection.Adornee = nil
	objValue.Value = nil
	gui.Enabled = false
	State = false
end)

game:GetService("UserInputService").InputBegan:Connect(function(input)
	if tool.Parent:FindFirstChild("Humanoid") then
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch or input.KeyCode == Enum.KeyCode.ButtonR2 then
			State = true
			track:Play()
		end
	end
end)

game:GetService("UserInputService").InputEnded:Connect(function(input)
	if tool.Parent:FindFirstChild("Humanoid") then
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch or input.KeyCode == Enum.KeyCode.ButtonR2 then
			State = false
			track:Stop()
		end
	end
end)

tool.GetBlockData.OnClientEvent:Connect(function(speed, strength, value)
	Speed = speed
	Strength = strength
	Value = value
end)

runService.RenderStepped:Connect(function()
	if tool.Parent:FindFirstChild("Humanoid") then
		local target = mouse.Target
		if target then
			if collectionService:HasTag(target.Parent, "Block") then
				selection.Adornee = target
				objValue.Value = target.Parent

				gui.Block.Text = target.Parent.Name
				gui.Hp.Text = objValue.Value:GetAttribute("Health")
				gui.Enabled = true

				if lastTarget ~= target then
					bar.Position = UDim2.new(-1,0,0,0)
					tool.GetBlockData:FireServer(target.Parent:GetAttribute("Id"), tool:GetAttribute("Speed"), tool:GetAttribute("Strength"), tool:GetAttribute("RemoveBy"))
				end

				lastTarget = target
			else
				selection.Adornee = nil
				objValue.Value = nil
				gui.Enabled = false
				Speed = nil
				Strength = nil
				bar.Position = UDim2.new(-1,0,0,0)
			end
		else
			selection.Adornee = nil
			objValue.Value = nil
			gui.Enabled = false
			Speed = nil
			Strength = nil
			bar.Position = UDim2.new(-1,0,0,0)
		end
	end
	
	if State then
		if Speed and Strength and objValue.Value then
			local block = objValue.Value
			gui.Hp.Text = block:GetAttribute("Health")
			if mineDebounce == false then
				bar.Position += UDim2.new(Speed*toolSpeed,0,0,0)
				if bar.Position.X.Scale >= 0 then
					mineDebounce = true
					bar.Position = UDim2.new(-1,0,0,0)
					local oldHealth = block:GetAttribute("Health")
					block:SetAttribute("Health", (block:GetAttribute("Health") - tool:GetAttribute("RemoveBy")))
					if block:GetAttribute("Health") < 0 then
						block:SetAttribute("Health", 0)
					end
					local newHealth = block:GetAttribute("Health")
					tool.AddCapacity:FireServer(oldHealth - newHealth, tool:GetAttribute("Speed"), tool:GetAttribute("Strength"), tool:GetAttribute("RemoveBy"))
					if block:GetAttribute("Health") <= 0 then
						tool.Mine:FireServer(objValue.Value, tool:GetAttribute("Speed"), tool:GetAttribute("Strength"), tool:GetAttribute("RemoveBy"))
					end
					if block:GetAttribute("Health") > 0 then
						mineDebounce = false
					end
				end
			end
		end
	else
		bar.Position = UDim2.new(-1,0,0,0)
	end
end)

tool.Mine.OnClientEvent:Connect(function()
	bar.Position = UDim2.new(-1,0,0,0)
	objValue.Value = nil
	mineDebounce = false
end)

if you are playing a track , animation, that will always play at a same speed, is this what swings the pickaxe?

How are any of the variables going to change an animation playing speed?

along with that, what is your animation priority set to, or whatever that thing is called… maybe that relates

fps probably too high

hmm? where is that defined? at in studio

you’re calling this every frame on the client, so to fix it you’ll need to use the delta parameter that RenderStepped gives you, so add that into the parenthesis:

runService.RenderStepped:Connect(function(delta)

delta is basically the amount of time that’s passed each frame. so if you had a stable 60fps, it would be 1/60. if you had a stable 144fps, it’d be 1/144.
then after that, you’ll want to use it to make the bar frame-rate independent, by multiplying the bar speed by the delta like so

bar.Position += UDim2.new((Speed*toolSpeed) * (delta*60),0,0,0) -- this should make it move at around the same speed as Studio

this should fix the issue you’re having.

i do have a couple things to note:
  1. it could be better to make the bar represent a timer using os.clock() or similar instead of adding to the bar each frame. that way, the bar can’t be affected by fluctuations in frame-rate.

  2. trusting the client to time themselves and send tool attributes truthfully is risky, an exploiter could spoof your remote events and wreak havoc across your game. you should always treat the client as if they’re lying.
    consider having the server run some sanity checks to make sure that the client has been mining the block for a reasonable amount of time (give or take a few seconds for ping), and that they’re only mining an amount of blocks reasonable for the tool the server sees them using.

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