Hello.
When testing this script, when the swingPart is slowing, it snaps to the initialCFrame near the end. I have tried and tried but cannot fix any of it and am really confused. If anyone could help me, it would be greatly apricated.
local RunService = game:GetService("RunService")
local swingPart = workspace.RideSystem.Parts.SwingArm.MovePart
local maxAmplitude = 120 -- Max swing amplitude (degrees)
local initialSwingSpeed = 0.75 -- Speed for oscillation
local holdTime = 15 -- Time to swing at the peak (seconds)
local totalTime = 45 -- Total time for the full cycle (seconds)
local resetDuration = 2 -- Time to smoothly reset back to the initial position
local eTime = 0 -- Elapsed time
local swingAmplitude = 0 -- Current amplitude
local isSwinging = true -- Flag to indicate if the swing is active
local isResetting = false -- Flag to indicate if the swing is resetting
local function lerp(a, b, t)
return a + (b - a) * t
end
local initialCFrame = swingPart.CFrame
RunService.Heartbeat:Connect(function(deltaTime)
if isSwinging then
eTime += deltaTime
if eTime < totalTime then
if eTime < (totalTime / 3) then
local progress = eTime / (totalTime / 3)
swingAmplitude = lerp(10, maxAmplitude, progress) -- Amplitude increases to max amplitude
elseif eTime < (totalTime / 3) + holdTime then
swingAmplitude = maxAmplitude -- Swinngs at max amplitude
else
local progress = (eTime - (totalTime / 3) - holdTime) / (totalTime / 3)
swingAmplitude = lerp(maxAmplitude, 0, progress) -- Amplitude decreases to 0
end
local swingAngle = math.sin(eTime * initialSwingSpeed) * math.rad(swingAmplitude)
swingPart.CFrame = initialCFrame * CFrame.Angles(swingAngle, 0, 0)
else
isSwinging = false
isResetting = true
eTime = 0
end
elseif isResetting then
local progress = eTime / resetDuration
swingPart.CFrame = swingPart.CFrame:Lerp(initialCFrame, progress)
eTime += deltaTime
if eTime >= resetDuration then
swingPart.CFrame = initialCFrame
isResetting = false
end
end
end)```
I can’t be sure because the calculations hurt my brain but it appears to me there’s an issue with the final eTime number that’s causing this, possibly with the lerp of the swingAmplitude.
I have printed them out and the last two prints are not like the rest. Normally the swingAmpltude between prints are very very small, like 0.05 small. The last two has a jump of around 0.15
Just before last print:
eTime = 44.977358057396486
initialSwingSpeed = 0.75
swingAmplitude = 0.1811355408281088
So have a look at swingAmplitude since it’s 1/3rd the value and the difference seems to be what’s causing the issue when you multiply by .181 or .037.
Try printing the variables before this code calculation to see where the 3x difference is. If it doesn’t give you any clues keep tracking back to the previous calculation.
Okay so I have done some testing and managed to get it so it runs another lerp for slow and steady movements at the end. I am not sure if its because my brain is fried or what but I am running into the issue now that the rotating swing part resets to its original CFrame and then runs them tweens. I am guessing this is because the first main motion is returning it to the original CFrame, but I have no idea how to stop that.
If you have any ideas, it would be an amazing help
local RunService = game:GetService("RunService")
local swingPart = workspace.RideSystem.Parts.SwingArm.MovePart
local maxAmplitude = 120 -- Max swing amplitude (degrees)
local initialSwingSpeed = 0.75 -- Speed for oscillation
local holdTime = 15 -- Time to swing at the peak (seconds)
local totalTime = 45 -- Total time for the full cycle (seconds)
local resetDuration = 5 -- Time to smoothly reset back to the initial position
local eTime = 0 -- Elapsed time
local swingAmplitude = 0 -- Current amplitude
local isSwinging = true -- Flag to indicate if the swing is active
local isResetting = false -- Flag to indicate if the swing is resetting
local function lerp(a, b, t)
return a + (b - a) * t
end
local function easeOutSine(t)
return math.sin((t * math.pi) / 2)
end
local initialCFrame = swingPart.CFrame
RunService.Heartbeat:Connect(function(deltaTime)
if isSwinging then
eTime += deltaTime
if eTime < totalTime then
if eTime < (totalTime / 3) then
local progress = eTime / (totalTime / 3)
swingAmplitude = lerp(10, maxAmplitude, progress) -- Amplitude increases to max amplitude
elseif eTime < (totalTime / 3) + holdTime then
swingAmplitude = maxAmplitude -- Swings at max amplitude
else
local progress = (eTime - (totalTime / 3) - holdTime) / (totalTime / 3)
swingAmplitude = lerp(maxAmplitude, 0, progress) -- Amplitude decreases to 0
end
local swingAngle = math.sin(eTime * initialSwingSpeed) * math.rad(swingAmplitude)
swingPart.CFrame = initialCFrame * CFrame.Angles(swingAngle, 0, 0)
else
isSwinging = false
isResetting = true
eTime = 0
end
elseif isResetting then
eTime += deltaTime
local progress = eTime / resetDuration
local easedProgress = easeOutSine(progress)
local swingAngle = math.sin(eTime * initialSwingSpeed) * math.rad(5 * (1 - easedProgress))
local reversedSwingAngle = swingAngle * -1
local targetCFrame = initialCFrame * CFrame.Angles(reversedSwingAngle, 0, 0)
swingPart.CFrame = swingPart.CFrame:Lerp(targetCFrame, easedProgress)
if eTime >= resetDuration then
swingPart.CFrame = initialCFrame
isResetting = false
end
end
end)