Im trying to make a spear throw, and i dont know the best way to do this, i’ve tried using bezier curves and this has worked the best so far, but its a bit strange and i’ve never really used bezier curves. i’ve searched for some answers and nothing really sticks out all too much, i dont know if body velocities would work for my case, because i want the spear to end up where your mouse.
this is what i have so far but the spear timing to reach its end position is a bit innacurate and looks strange, also this is just for testing and doesnt have a spear model, i followed a tutorial by someone for the bezier curves. If you have any ideas or different approaches, please let me know!
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DamageRemote = Remotes:WaitForChild("Damage")
local SpearThrow = Remotes:WaitForChild("Weapons"):WaitForChild("Spear"):WaitForChild("SpearThrow")
local function lerp(t, a, b)
return a + (b - a) * t
end
local function quad(t, p0, p1, p2)
local l1 = lerp(t, p0, p1)
local l2 = lerp(t, p1, p2)
local quad = lerp(t, l1, l2)
return quad
end
SpearThrow.OnServerEvent:Connect(function(player, startPos, endPos)
local p1 = Instance.new("Part", workspace.ProjectilesHitboxes)
p1.Size = Vector3.one
p1.Color = Color3.new(0.219608, 0.466667, 1)
p1.Position = startPos
p1.Anchored = true
p1.CanCollide = false
p1.CanQuery = false
p1.CanTouch = false
local MaxDistance = 75
local direction = (endPos - startPos)
local horizontalDir = Vector3.new(direction.X, 0, direction.Z)
local distance = horizontalDir.Magnitude
if distance > MaxDistance then
horizontalDir = horizontalDir.Unit * MaxDistance
end
local origin = startPos + horizontalDir
local finalEndPos
if direction.Magnitude < MaxDistance then
finalEndPos = endPos
else
local Raycast = workspace:Raycast(startPos + horizontalDir, Vector3.new(0, -100, 0))
if Raycast then
finalEndPos = Raycast.Position
end
end
local p2 = Instance.new("Part", workspace.ProjectilesHitboxes)
p2.Size = Vector3.one
p2.Color = Color3.new(1, 0.294118, 0.305882)
p2.Position = finalEndPos
p2.Anchored = true
p2.CanCollide = false
p2.CanQuery = false
p2.CanTouch = false
local p1p2MidPoint = 0.5 * (startPos + finalEndPos)
local distance = (startPos - finalEndPos).Magnitude
local arcHeight = distance / 4
local p3FinalPosition = p1p2MidPoint + Vector3.new(0, arcHeight, 0)
local p3 = Instance.new("Part", workspace.ProjectilesHitboxes)
p3.Size = Vector3.one
p3.Color = Color3.new(0.411765, 1, 0.25098)
p3.Position = p3FinalPosition
p3.Anchored = true
p3.CanCollide = false
p3.CanQuery = false
p3.CanTouch = false
local p4 = Instance.new("Part", workspace.ProjectilesHitboxes)
p4.Size = Vector3.one
p4.Color = Color3.new(1, 1, 1)
p4.Position = p1.Position
p4.Anchored = true
p4.CanCollide = false
p4.CanQuery = false
p4.CanTouch = false
local MaxDuration = 1
local distance = (endPos - startPos).Magnitude
local duration = math.clamp((distance / MaxDistance) * MaxDuration, 0, MaxDuration)
local elapsed = 0
local connection
connection = RunService.Heartbeat:Connect(function(dt)
elapsed += dt
local t = elapsed / duration
local position = quad(t, p1.Position, p3.Position, p2.Position)
p4.Position = position
if t >= 1 then
connection:Disconnect()
end
end)
end)

