Hi Im trying to make Mirana’s ability from the anime called “Dota:Dragon’s Blood”. Im trying to make rain of arrows. But theres a problem. Hitbox. Idk why but it glitches and stops at the air. Please help me
local folder = game:GetService(“ReplicatedStorage”)
local function ar()
script.Parent.CFrame = CFrame.lookAt(script.Parent.Position, workspace.TARRR.Position)
local pos = Vector3.new(script.Parent.CFrame.X+math.random(-20,20),script.Parent.CFrame.Y+math.random(-10,10),script.Parent.Position.Z)
local arrow = folder.Folder.Arrow:Clone()
arrow.Parent = script.Parent
game.Debris:AddItem(arrow,5)
arrow.CFrame = CFrame.new(pos)
local newforce = Instance.new("BodyForce")
newforce.Force = Vector3.new(0,workspace.Gravity * arrow:GetMass(), 0)
newforce.Parent = arrow
local bodyvel = Instance.new("BodyVelocity")
bodyvel.Parent = arrow
bodyvel.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bodyvel.Velocity = (workspace.TARRR.Position - script.Parent.Position).unit * 110
arrow.Orientation = script.Parent.Orientation
arrow.HitBox.Touched:Connect(function(hit)
if hit.Name~="Arrow" and hit.Name~= "HitBox" and hit:IsA("Part") then
print(hit)
arrow.Anchored=true
end
end)
end
task.delay(0.1,function()
while wait(0.1) do
ar()
ar()
end
end)
BodyForce cancels gravity completely newforce.Force = Vector3.new(0,workspace.Gravity * arrow:GetMass(), 0)
That makes the arrow float forever. Gravity never pulls it down.
BodyVelocity forces constant motion
It keeps applying the same velocity every frame, so there’s no “falling” curve — just a flat, constant-speed line. When Roblox’s physics engine pauses or body forces conflict, it looks like it froze.
Too many arrows too fast while wait(0.1) do ar(); ar(); end creates 20 arrows per second. Roblox throttles physics when too many parts exist, especially if each arrow has multiple BodyMovers.
Arrow may touch itself immediately
That can trigger .Touched instantly and anchor it right away.
Fixed version.
local folder = game:GetService("ReplicatedStorage")
local target = workspace:WaitForChild("TARRR")
local function fireArrow()
local arrow = folder.Folder.Arrow:Clone()
arrow.Parent = script.Parent
arrow.Anchored = false
arrow.CanCollide = true
-- random offset spawn position
local pos = script.Parent.Position + Vector3.new(math.random(-20,20), math.random(-10,10), 0)
arrow.CFrame = CFrame.lookAt(pos, target.Position)
-- apply impulse (preferred over BodyVelocity)
local dir = (target.Position - pos).Unit
local speed = 110
arrow:ApplyImpulse(dir * speed * arrow:GetMass())
game.Debris:AddItem(arrow, 5)
-- hit detection
local hitbox = arrow:FindFirstChild("HitBox")
if hitbox then
hitbox.Anchored = false
hitbox.Touched:Connect(function(hit)
if hit:IsDescendantOf(arrow) then return end
if hit:IsA("Part") and hit.Name ~= "Arrow" and hit.Name ~= "HitBox" then
print("Hit:", hit)
arrow.Anchored = true
arrow:ClearAllChildren() -- optional: stop physics forces
end
end)
end
end
-- fire continuously
task.spawn(function()
while task.wait(0.2) do
fireArrow()
end
end)
I would also recommend using raycasts and tweening them to the hit position instead of physics, as they are way more performant at scale.
local folder = game:GetService("ReplicatedStorage")
local target = workspace:WaitForChild("TARRR")
local tweenService = game:GetService("TweenService")
-- Config
local MAX_DISTANCE = 500
local ARROW_SPEED = 110 -- studs per second
local function fireArrow()
local arrow = folder.Folder.Arrow:Clone()
arrow.Parent = script.Parent
arrow.Anchored = true
arrow.CanCollide = false
-- random offset
local startPos = script.Parent.Position + Vector3.new(math.random(-20,20), math.random(-10,10), 0)
local dir = (target.Position - startPos).Unit
arrow.CFrame = CFrame.lookAt(startPos, startPos + dir)
-- Raycast setup
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances = {script.Parent, arrow}
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.IgnoreWater = true
local result = workspace:Raycast(startPos, dir * MAX_DISTANCE, rayParams)
local hitPos = result and result.Position or (startPos + dir * MAX_DISTANCE)
local distance = (hitPos - startPos).Magnitude
local travelTime = distance / ARROW_SPEED
-- Tween arrow to hit position
local tween = tweenService:Create(
arrow,
TweenInfo.new(travelTime, Enum.EasingStyle.Linear),
{CFrame = CFrame.lookAt(hitPos, hitPos + dir)}
)
tween:Play()
tween.Completed:Connect(function()
if result then
-- Hit something
print("Hit:", result.Instance)
local hit = result.Instance
-- Optionally "stick" arrow at hit
local stuck = folder.Folder.Arrow:Clone()
stuck.Anchored = true
stuck.CFrame = CFrame.lookAt(hitPos, hitPos + dir)
stuck.Parent = hit
game.Debris:AddItem(stuck, 5)
end
arrow:Destroy()
end)
end
-- Fire continuously
task.spawn(function()
while task.wait(0.2) do
fireArrow()
end
end)
Thats why i used velocity and bodyforce. I wanted arrows to shoot from math random positions of script.Parent and just fly toward the target. Now the arrows dont shoot toward the target, now they shoot at the target
my bad this will make in a square area give the rain affect with raycast and then tween on a hit to that position instead having to rely on slow physics
local folder = game:GetService("ReplicatedStorage")
local tweenService = game:GetService("TweenService")
-- ⚙️ Config
local AREA_CENTER = Vector3.new(0, 100, 0) -- Center point of rain zone (above ground)
local AREA_SIZE = Vector2.new(200, 200) -- Width/Depth of rain zone
local ARROW_SPEED = 180 -- Studs per second (controls fall speed)
local FALL_ANGLE = 15 -- Degrees, tilt from vertical
local MAX_DISTANCE = 300 -- How far arrows fall before disappearing
local FIRE_INTERVAL = 0.05 -- How often to spawn arrows (smaller = denser rain)
-- 🔥 Arrow spawn function
local function spawnArrow()
local arrow = folder.Folder.Arrow:Clone()
arrow.Parent = workspace
arrow.Anchored = true
arrow.CanCollide = false
-- Pick a random spawn position within area
local x = AREA_CENTER.X + math.random(-AREA_SIZE.X/2, AREA_SIZE.X/2)
local z = AREA_CENTER.Z + math.random(-AREA_SIZE.Y/2, AREA_SIZE.Y/2)
local startPos = Vector3.new(x, AREA_CENTER.Y, z)
-- Calculate fall direction (15° forward tilt)
local angle = math.rad(FALL_ANGLE)
local forwardDir = Vector3.new(0, -math.cos(angle), math.sin(angle)) -- tilts slightly forward (Z+)
forwardDir = forwardDir.Unit
arrow.CFrame = CFrame.lookAt(startPos, startPos + forwardDir)
-- Raycast to find where it would hit (e.g., ground or object)
local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {arrow}
rayParams.IgnoreWater = true
local result = workspace:Raycast(startPos, forwardDir * MAX_DISTANCE, rayParams)
local hitPos = result and result.Position or (startPos + forwardDir * MAX_DISTANCE)
local distance = (hitPos - startPos).Magnitude
local travelTime = distance / ARROW_SPEED
-- Tween arrow toward the ground
local tween = tweenService:Create(
arrow,
TweenInfo.new(travelTime, Enum.EasingStyle.Linear),
{CFrame = CFrame.lookAt(hitPos, hitPos + forwardDir)}
)
tween:Play()
tween.Completed:Connect(function()
if result then
-- Create "stuck" arrow
local stuck = folder.Folder.Arrow:Clone()
stuck.Anchored = true
stuck.CFrame = CFrame.lookAt(hitPos, hitPos + forwardDir)
stuck.Parent = result.Instance
game.Debris:AddItem(stuck, 5)
end
arrow:Destroy()
end)
end
-- 🌧️ Continuous arrow rain loop
task.spawn(function()
while task.wait(FIRE_INTERVAL) do
spawnArrow()
end
end)
it keeps working very weird. Like i want arrows go from script.Parent, not from the sky, and shoot toward the target, not at it. The second script u sent was just a rain of arrows from the sky, that cant be moved. I need arrows shoot from script.Parent, bc when i will script it as an ability, then i will need to spawn block(its gonna be a magical sphere when particles) that will shoot with arrows
Its using code position and size if u say script.Parent is the part it need to rain from size and position wise u can change these 2 lines
local AREA_CENTER = script.Parent.Position --Vector3.new(0, 100, 0) -- Center point of rain zone (above ground)
local AREA_SIZE = Vector2.new(script.Parent.Size.X, script.Parent.Size.Z) --Vector2.new(200, 200) -- Width/Depth of rain zone
its coded that it rains down by 15 deg angle if u want it to change the angle also change the degrees with
local FALL_ANGLE = 15 -- Degrees, tilt from vertical
local folder = game:GetService("ReplicatedStorage")
local tweenService = game:GetService("TweenService")
-- 🟩 Source (spawning area)
local green = script.Parent
-- 🟥 Target (impact area)
local red = workspace.TARRR
-- ⚙️ Config
local ARROW_SPEED = 180
local FIRE_INTERVAL = 0.05
local MAX_DISTANCE = 1000 -- safety distance for long tweens
-- 🧮 Utility: get a random position within a part’s bounds
local function getRandomPointInPart(part)
local size = part.Size
local cf = part.CFrame
local offset = Vector3.new(
math.random(-size.X/2, size.X/2),
math.random(-size.Y/2, size.Y/2),
math.random(-size.Z/2, size.Z/2)
)
return (cf.Position + cf:VectorToWorldSpace(offset))
end
-- 🏹 Spawn function
local function spawnArrow()
local arrow = folder.Folder.Arrow:Clone()
arrow.Parent = workspace
arrow.Anchored = true
arrow.CanCollide = false
-- Random spawn (green) and target (red)
local startPos = getRandomPointInPart(green)
local endPos = getRandomPointInPart(red)
local dir = (endPos - startPos).Unit
local distance = (endPos - startPos).Magnitude
local travelTime = distance / ARROW_SPEED
arrow.CFrame = CFrame.lookAt(startPos, startPos + dir)
-- Raycast for realism (to stop early if hitting something mid-air)
local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {arrow, green}
rayParams.IgnoreWater = true
local result = workspace:Raycast(startPos, dir * distance, rayParams)
if result then
endPos = result.Position
travelTime = (endPos - startPos).Magnitude / ARROW_SPEED
end
-- Tween from green → red
local tween = tweenService:Create(
arrow,
TweenInfo.new(travelTime, Enum.EasingStyle.Linear),
{CFrame = CFrame.lookAt(endPos, endPos + dir)}
)
tween:Play()
tween.Completed:Connect(function()
if result then
-- Stick arrow into hit surface
local stuck = folder.Folder.Arrow:Clone()
stuck.Anchored = true
stuck.CFrame = CFrame.lookAt(endPos, endPos + dir)
stuck.Parent = result.Instance
game.Debris:AddItem(stuck, 5)
end
arrow:Destroy()
end)
end
-- 🌧️ Continuous rain
task.spawn(function()
while task.wait(FIRE_INTERVAL) do
spawnArrow()
end
end)
should use green parts position and bounds the spawn the arrows spread inside of it volume random and rain towards the red part and spread to those size and bounds