Issue with knife throwing

Hello. I’m currently having an issue with a knife throwing system where in-game (not studio), the knife moves at extremely slower rates than it should.

EDIT: whoops, i didn’t know streamable links didn’t embed here. i’m not sure how to embed these properly since file size is too big on them

Here is a video showing this.

External Media

This video below is how it is in studio.

External Media

Here is the core code for handling the throwing (this code is all handled on the client.):

if State == "KnifeThrown" then
		local knifeCon
		local Rotated = false
		knifeCon = Heartbeat.Stepped:Connect(function()
			local targetPos = item1
			local direction = (targetPos - item2.Position).Unit
			local newPosition = item2.Position + direction * 15 * 0.1
			item2.Position = newPosition
			if Rotated == false then
				Rotated = true
				item2.CFrame = CFrame.lookAt(item2.Position, targetPos)
			end
			item2.CFrame *= CFrame.Angles(math.rad(-10), math.rad(0), math.rad(0))
			for i, v in item2:GetChildren() do
				if v:IsA("Part") or v:IsA("UnionOperation") then
					v.CFrame = item2.CFrame
				end
			end
			local params = RaycastParams.new()
			params.FilterDescendantsInstances = item4
			params.FilterType = Enum.RaycastFilterType.Exclude

			--Creates a ray every tick to check if an enemy has interruped the ray.
			local raycastResult = workspace:Raycast(item2.Position,(item1 - item3).Unit*5,params) 
			if raycastResult then	

				local Killed = false
				local Broken = false
				
				if raycastResult.Instance then
					
					local PossibleModel = raycastResult.Instance:FindFirstAncestorWhichIsA("Model")
					if PossibleModel then
						local Humanoid = PossibleModel:FindFirstChildWhichIsA("Humanoid")
						local Killer = PossibleModel:FindFirstChild("Killer")
						if Killer then
							if Humanoid and Humanoid.Health > 0 then
								if Killed == false then
									knifeCon:Disconnect()
									Killed = true
									game.ReplicatedStorage.Events.Remotes.ClientEvent:FireServer("Killed", Killer, Humanoid, PossibleModel)
									if item2 then
										item2:Destroy()
									end			
								end
						end
						else
							if raycastResult.Instance:IsA("BasePart") then
								if raycastResult.Instance.Name == "TS_Tile" then	
									if Broken == false then
										Broken = true
										knifeCon:Disconnect()
										game.ReplicatedStorage.Events.Remotes.ClientEvent:FireServer("TileSmash", raycastResult.Instance)	
										if item2 then
											item2:Destroy()
										end
									end
								end
							end
						end
					end
				end
			end
			
			if (newPosition - targetPos).Magnitude < 0.75 then
				local surf = Instance.new("Sound", item2)
				surf.SoundId = item5
				surf.Volume = 1
				surf.PlayOnRemove = true
				surf:Destroy()
				task.delay(1.5, function() item2:Destroy() end)	
				knifeCon:Disconnect();
				return;
			end
		end)
	end

Is your maximum framerate in studio set to something higher than 60? The RunService.Heartbeat in studio is dependent on your framerate, but the RunService.Heartbeat rate in game is always 60.

So when you are in studio there are more ticks per second than in game, if your framerate cap is higher.

  • At 30 Fps, the knife moves 45 studs/second
  • At 60 Fps, the knife moves 90 studs/second
  • Etc

You could do something like this:

local RunService = game:GetService("RunService")

local elapsed = 0
local tickRate = 1/60 -- 60 ticks per sec

knifeCon = RunService.Heartbeat:Connect(function(deltaTime)
    elapsed += deltaTime

    while elapsed >= tickRate then
        elapsed -= tickRate

        -- Anything else to run in your simulation
    end
end)

Sorry if this is unclear, your code is a little hard to decipher.