How to fix a LinearVelocity script that glitches over time

I’m currently developing a game where you block arrows. However, I’ve run into a really annoying problem. The issue is that the LinearVelocity, which works perfectly fine at first, starts to glitch and jitter back and forth over time. The script and video are provided below. It might not even be a problem with LinearVelocity itself, but please take a look.

local PhysicsService = game:GetService("PhysicsService")

local ok, _ = pcall(function()
	PhysicsService:CreateCollisionGroup("Arrows")
end)

PhysicsService:CollisionGroupSetCollidable("Arrows", "Arrows", false)

local ArrowIdCounter = 0

local function particleimpact(position)
	local ParticlePart = workspace:WaitForChild("Hit"):Clone()
	ParticlePart.CFrame = position
	ParticlePart.Parent = workspace
	-- 사운드 중 하나만 랜덤 재생
	local sounds = {}
	for _, v in pairs(ParticlePart:GetChildren()) do
		if v:IsA("Sound") then
			table.insert(sounds, v)
		end
	end
	if #sounds > 0 then
		local chosen = sounds[math.random(1, #sounds)]
		chosen:Play()
	end
	wait(0.05)
	-- 파티클 발사
	for _, v in pairs(ParticlePart:GetDescendants()) do
		if v:IsA("ParticleEmitter") then
			v:Emit(1)
		end
	end
	-- 일정 시간 뒤 제거
	game.Debris:AddItem(ParticlePart, 2)
end

function onArrowTouched(arrow, hit)
	if not hit or not hit.Parent then return end
	local hitPlayer = Players:GetPlayerFromCharacter(hit.Parent)
	if not hitPlayer or not hitPlayer.Character then return end

	local formVal = (hitPlayer:FindFirstChild("Form") and hitPlayer.Form.Value) or "Normal"
	local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
	local arrowName = arrow.Name
	local rootPart = hitPlayer.Character:FindFirstChild("HumanoidRootPart")
	if not rootPart then return end

	local distance = (arrow.Position - rootPart.Position).Magnitude

	local isLeft = arrowName:find("LeftArrow") == 1
	local isRight = arrowName:find("RightArrow") == 1
	local isUp = arrowName:find("UpArrow") == 1

	local blockDistance = FORM_DESTROY_RADIUS[formVal] or 0

	if (formVal == "Left" and isLeft and distance <= blockDistance)
		or (formVal == "Right" and isRight and distance <= blockDistance)
		or (formVal == "Up" and isUp and distance <= blockDistance) then
		particleimpact(arrow.CFrame)
		arrow:Destroy()
		return
	end

	if distance <= 5 and humanoid then
		humanoid:TakeDamage(5)
	end

	arrow:Destroy()
end


--------------------------------------------------------
-- AssemblyLinearVelocity + VectorForce 기반 화살 이동
--------------------------------------------------------
--------------------------------------------------------
-- LinearVelocity 기반 화살 이동 (최신 & 안정적)
--------------------------------------------------------
local function launchArrowFromPartTemplate(spawnTemplate)
	if not spawnTemplate or not spawnTemplate:IsA("BasePart") then return end

	ArrowIdCounter += 1
	local arrow = spawnTemplate:Clone()
	arrow.Name = spawnTemplate.Name
	arrow.Anchored = false
	arrow.CanCollide = false
	arrow.Massless = true -- ✅ 중력 영향 제거
	arrow.Parent = workspace

	-- ✅ LinearVelocity (BodyVelocity 대체)
	local lv = Instance.new("LinearVelocity")
	lv.MaxForce = math.huge
	lv.VectorVelocity = spawnTemplate.CFrame.LookVector * ArrowSpeed
	lv.RelativeTo = Enum.ActuatorRelativeTo.World
	lv.Attachment0 = Instance.new("Attachment", arrow)
	lv.Parent = arrow

	-- 🔹 화살끼리 충돌하지 않게 그룹 지정
	local PhysicsService = game:GetService("PhysicsService")
	PhysicsService:SetPartCollisionGroup(arrow, "Arrows")

	-- ✅ 중력 완전 무시
	local noGravity = Instance.new("VectorForce")
	noGravity.ApplyAtCenterOfMass = true
	noGravity.Force = Vector3.new(0, workspace.Gravity * arrow.AssemblyMass, 0)
	noGravity.Attachment0 = lv.Attachment0
	noGravity.Parent = arrow

	-- 🎯 충돌 처리
	arrow.Touched:Connect(function(hit)
		onArrowTouched(arrow, hit)
	end)

	game.Debris:AddItem(arrow, ArrowLifetime)
end


--------------------------------------------------------
-- RemoteEvent 처리
--------------------------------------------------------
event.OnServerEvent:Connect(function(player, code)
	local value = player:WaitForChild("Form")

	if code == "Left" then
		value.Value = "Left"
		if value.Value == 'Left' then
		wait(0.2)
		value.Value = "Normal"
		end
	elseif code == "Right" then
		value.Value = "Right"
		if value.Value == 'Right' then
		wait(0.2)
		value.Value = "Normal"
		end
	elseif code == "Up" then
		value.Value = "Up"
		if value.Value == 'Up' then
		wait(0.2)
		value.Value = "Normal"
		end
	elseif code == "start" then
		ArrowIdCounter = 0  

		local Leftarrow = Workspace:WaitForChild("LeftArrow")
		local Rightarrow = Workspace:WaitForChild("RightArrow")
		local Uparrow = Workspace:WaitForChild("UpArrow")

		local ArrowTemplates = {Leftarrow, Rightarrow, Uparrow}
		local ArrowAmount = 20
			for i = 1, ArrowAmount do
				local chosenTemplate = ArrowTemplates[math.random(1, #ArrowTemplates)]
				launchArrowFromPartTemplate(chosenTemplate)
				task.wait(math.random(5, 10) / 10) -- 0.5~1초 랜덤
			end
			wait(1)
			event:FireClient(player, 'restart')
	end

end)

1 Like

It might be related to network ownership, try to check ownership with developer console (Screenshots below).

If you see that the outline changes at the moment this problem occurs, then when creating a part, assign it Part:SetNetworkOwner(nil)


Exactly, I set network ownership to nil and it’s resolved!

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