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)
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:
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.
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.