Ok so, first of all,
In the example I made there’s a mistake ( I think) :
the time value for quadratic curve is supposed to be 0 <= t <= 1
To convert timeElapsed to time for curve, you do
local t = timeElapsed/duration
local pointAtTimeElapsed = bezier(t, start, mid, endPos)
Your speed variable isn’t exactly speed; it’s the delay between tweens
Here’s how you can implement speed
local speed = script.Parent:GetAttribute("speed") -- insert your value (I use between 1-2)
local duration = (armStartCf.p - pivotCFrame.Position).Magnitude / speed
You might notice there’s a armStartCf variable; that’s the solution to your problem.
Here lies the problem:
local pointAtTimeElapsed = Bezier_Module:QuadraticBezier(timeElapsed,arm.Position,(arm.CFrame * rndCF).p, pivotCFrame.p)
local lookAt = Bezier_Module:QuadraticBezier(timeElapsed+speed,arm.Position,(arm.CFrame * rndCF).p, pivotCFrame.p)
arm.CFrame = CFrame.new(pointAtTimeElapsed,Bezier_Module:QuadraticBezier(timeElapsed+.01,arm.Position,(arm.CFrame * rndCF).p, pivotCFrame.p))
Your start and middle position is not constant, the curve tries to get to the turning point, but it never reaches it since it is always behind resulting in a spiral.
Just change
arm.Position
into armStartCf.p
and
arm.CFrame * rndCf
into armStartCf * rndCf
where armStartCf is the starting CFrame of the arm // spawn cframe of the arm
Here’s the code that I used
local TweenService = game:GetService("TweenService")
local arm = nil
local pivotCFrame = CFrame.new(script.Parent.Attachment.WorldPosition)
local Bezier_Module = {}
script.Parent:SetAttribute("speed", 2)
function Bezier_Module:QuadraticBezier(Time,Point0,Point1,Point2)
return (1-Time)^2*Point0+2*(1-Time)*Time*Point1+Time^2*Point2; --This'll give you that curve you were looking for :)
end;
local function TweenArm(arm)
spawn(function()
local armStartCf = arm.CFrame
local timeElapsed = 0
local rnd = Random.new()
local rndCF = CFrame.new(rnd:NextInteger(-1,1),rnd:NextNumber(-2.5,2.5),rnd:NextNumber(-5,-5.5))
local speed = script.Parent:GetAttribute("speed")
local duration = (armStartCf.p - pivotCFrame.Position).Magnitude / speed
local tweenDelay = 0.1
local new = Instance.new("Part")
new.CFrame = arm.CFrame * rndCF
new.Size = Vector3.new(1,1,1)
new.Anchored = true
new.CanCollide = false
new.Material = Enum.Material.Neon
new.Parent = script.Parent
game.Debris:AddItem(new, 1)
print(duration)
--while timeElapsed < duration do
-- local pointAtTimeElapsed = Bezier_Module:QuadraticBezier(timeElapsed,armStartCf,(arm.CFrame * rndCF).p, pivotCFrame.p)
-- local new = Instance.new("Part")
-- new.Position = pointAtTimeElapsed
-- new.Size = Vector3.new(.2,.2,.2)
-- new.Anchored = true
-- new.CanCollide = false
-- new.Material = Enum.Material.Neon
-- new.Parent = script.Parent
-- game.Debris:AddItem(new, 1)
---- arm.CFrame = CFrame.new(pointAtTimeElapsed,Bezier_Module:QuadraticBezier(timeElapsed+.001,arm.Position,(arm.CFrame * rndCF).p, pivotCFrame.p)) -- Makes the arm face the right way
-- timeElapsed += 0.01
--end
timeElapsed = 0
while timeElapsed < duration do
local progress = timeElapsed / duration
local pointAtTimeElapsed = Bezier_Module:QuadraticBezier(progress,armStartCf.p,(armStartCf * rndCF).p, pivotCFrame.p)
local lookAt = Bezier_Module:QuadraticBezier(progress+0.01,armStartCf.p,(armStartCf * rndCF).p, pivotCFrame.p)
if timeElapsed == 0 then
arm.CFrame = CFrame.new(pointAtTimeElapsed,Bezier_Module:QuadraticBezier(progress+.01,armStartCf.p,(armStartCf * rndCF).p, pivotCFrame.p)) -- Makes the arm face the right way
elseif timeElapsed == speed then
local tween = TweenService:Create(arm,TweenInfo.new(.4),{Transparency = 0}):Play()
end
timeElapsed += speed
local tween = TweenService:Create(arm,TweenInfo.new(tweenDelay),{CFrame = CFrame.new(pointAtTimeElapsed,lookAt)})
tween:Play()
wait(tweenDelay)
end
arm:Destroy()
end)
end
while true do
local arm = script.Parent.Arm:Clone()
arm.Position = script.Parent.Position
arm.Parent = script.Parent
pivotCFrame = CFrame.new(script.Parent.Attachment.WorldPosition)
TweenArm(arm)
wait(0.5)
end
Also, you may want to increase the rndCf’s range to get a wider curve. (Like about half the maximum height of the curve you want)
(Think of the curve tool in MS Paint to get an idea how your curve would look like; set 2 points and drag the line to curve it)