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)

